From 0759b23448de29158367f344342e939dfa6eaf48 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Wed, 21 Aug 2019 11:00:08 -0400 Subject: moved links to own folder --- src/client/views/linking/LinkMenuItem.tsx | 282 ++++++++++++++++++++++++++++++ 1 file changed, 282 insertions(+) create mode 100644 src/client/views/linking/LinkMenuItem.tsx (limited to 'src/client/views/linking/LinkMenuItem.tsx') diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx new file mode 100644 index 000000000..7dc0a9fcd --- /dev/null +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -0,0 +1,282 @@ +import { library } from '@fortawesome/fontawesome-svg-core'; +import { faEdit, faEye, faTimes, faArrowRight, faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { observer } from "mobx-react"; +import { DocumentManager } from "../../util/DocumentManager"; +import { undoBatch } from "../../util/UndoManager"; +import './LinkMenu.scss'; +import React = require("react"); +import { Doc, DocListCastAsync } from '../../../new_fields/Doc'; +import { StrCast, Cast, FieldValue, NumCast } from '../../../new_fields/Types'; +import { observable, action } from 'mobx'; +import { LinkManager } from '../../util/LinkManager'; +import { DragLinkAsDocument } from '../../util/DragManager'; +import { CollectionDockingView } from '../collections/CollectionDockingView'; +import { SelectionManager } from '../../util/SelectionManager'; +import { CollectionViewType } from '../collections/CollectionBaseView'; +import { DocumentView } from '../nodes/DocumentView'; +library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp); + + +interface LinkMenuItemProps { + groupType: string; + linkDoc: Doc; + sourceDoc: Doc; + destinationDoc: Doc; + showEditor: (linkDoc: Doc) => void; + addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void; +} + +@observer +export class LinkMenuItem extends React.Component { + private _drag = React.createRef(); + @observable private _showMore: boolean = false; + @action toggleShowMore() { this._showMore = !this._showMore; } + + + unhighlight = () => { + Doc.UnhighlightAll(); + document.removeEventListener("pointerdown", this.unhighlight); + } + + @action + highlightDoc = () => { + document.removeEventListener("pointerdown", this.unhighlight); + Doc.HighlightDoc(this.props.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 = ({ col, target }: { col: Doc, target: 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; + 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 = () => { + this.highlightDoc(); + let alias = Doc.MakeAlias(this.props.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 (shouldZoom: boolean) => { + //there is an issue right now so this will be false automatically + shouldZoom = false; + this.highlightDoc(); + let jumpToDoc = this.props.destinationDoc; + let pdfDoc = FieldValue(Cast(this.props.destinationDoc, Doc)); + if (pdfDoc) { + jumpToDoc = pdfDoc; + } + let proto = Doc.GetProto(this.props.linkDoc); + let targetContext = await Cast(proto.targetContext, Doc); + let sourceContext = await Cast(proto.sourceContext, Doc); + let self = this; + + let dockingFunc = (document: Doc) => { this.props.addDocTab(document, undefined, "inTab"); SelectionManager.DeselectAll(); }; + + if (this.props.destinationDoc === self.props.linkDoc.anchor2 && targetContext) { + DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, async document => dockingFunc(document), undefined, targetContext); + } + else if (this.props.destinationDoc === self.props.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((this.props.destinationDoc === self.props.linkDoc.anchor2 ? self.props.linkDoc.anchor2Page : self.props.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 = () => { + this.highlightDoc(); + let fullScreenAlias = Doc.MakeAlias(this.props.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 = ({ col, target }: { col: Doc, target: 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; + col.panX = newPanX; + col.panY = newPanY; + } + // CollectionDockingView.Instance.AddRightSplit(col, undefined); + this.props.addDocTab(col, undefined, "inTab"); + SelectionManager.DeselectAll(); + } + + // this will open a link next to the source doc + @undoBatch + openLinkInPlace = () => { + this.highlightDoc(); + + let alias = Doc.MakeAlias(this.props.destinationDoc); + let y = this.props.sourceDoc.y; + let x = this.props.sourceDoc.x; + let parentView: any = undefined; + let parentDoc: Doc = this.props.sourceDoc; + + SelectionManager.SelectedDocuments().map(dv => { + if (dv.props.Document === this.props.sourceDoc) { + parentView = dv.props.ContainingCollectionView; + } + }); + + if (parentView) { + // console.log(parentDoc) + console.log(parentView.props.addDocument); + } + } + + //set this to be the default link behavior, can be any of the above + private defaultLinkBehavior: any = this.openLinkInPlace; + + onEdit = (e: React.PointerEvent): void => { + e.stopPropagation(); + this.props.showEditor(this.props.linkDoc); + SelectionManager.DeselectAll(); + } + + renderMetadata = (): JSX.Element => { + let groups = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, this.props.sourceDoc); + let index = groups.findIndex(groupDoc => StrCast(groupDoc.type).toUpperCase() === this.props.groupType.toUpperCase()); + let groupDoc = index > -1 ? groups[index] : undefined; + + let mdRows: Array = []; + if (groupDoc) { + let mdDoc = Cast(groupDoc.metadata, Doc, null); + if (mdDoc) { + let keys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);//groupMetadataKeys.get(this.props.groupType); + mdRows = keys.map(key => { + return (
{key}: {StrCast(mdDoc[key])}
); + }); + } + } + + return (
{mdRows}
); + } + + onLinkButtonDown = (e: React.PointerEvent): void => { + e.stopPropagation(); + document.removeEventListener("pointermove", this.onLinkButtonMoved); + document.addEventListener("pointermove", this.onLinkButtonMoved); + document.removeEventListener("pointerup", this.onLinkButtonUp); + document.addEventListener("pointerup", this.onLinkButtonUp); + } + + onLinkButtonUp = (e: PointerEvent): void => { + document.removeEventListener("pointermove", this.onLinkButtonMoved); + document.removeEventListener("pointerup", this.onLinkButtonUp); + e.stopPropagation(); + } + + onLinkButtonMoved = async (e: PointerEvent) => { + if (this._drag.current !== null && (e.movementX > 1 || e.movementY > 1)) { + document.removeEventListener("pointermove", this.onLinkButtonMoved); + document.removeEventListener("pointerup", this.onLinkButtonUp); + + DragLinkAsDocument(this._drag.current, e.x, e.y, this.props.linkDoc, this.props.sourceDoc); + } + e.stopPropagation(); + } + + render() { + + let keys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);//groupMetadataKeys.get(this.props.groupType); + let canExpand = keys ? keys.length > 0 : false; + + return ( +
+
+
+

{StrCast(this.props.destinationDoc.title)}

+
+ {canExpand ?
this.toggleShowMore()}> +
: <>} +
+ {/* Original */} + {/*
*/} + {/* New */} +
+
+
+ {this._showMore ? this.renderMetadata() : <>} +
+ +
+ ); + } +} + + // @undoBatch + // onFollowLink = async (e: React.PointerEvent): Promise => { + // e.stopPropagation(); + // e.persist(); + // let jumpToDoc = this.props.destinationDoc; + // let pdfDoc = FieldValue(Cast(this.props.destinationDoc, Doc)); + // if (pdfDoc) { + // jumpToDoc = pdfDoc; + // } + // let proto = Doc.GetProto(this.props.linkDoc); + // let targetContext = await Cast(proto.targetContext, Doc); + // let sourceContext = await Cast(proto.sourceContext, Doc); + // let self = this; + + + // let dockingFunc = (document: Doc) => { this.props.addDocTab(document, undefined, "inTab"); SelectionManager.DeselectAll(); }; + // if (e.ctrlKey) { + // dockingFunc = (document: Doc) => CollectionDockingView.Instance.AddRightSplit(document, undefined); + // } + + // if (this.props.destinationDoc === self.props.linkDoc.anchor2 && targetContext) { + // DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, async document => dockingFunc(document), undefined, targetContext!); + // console.log("1") + // } + // else if (this.props.destinationDoc === self.props.linkDoc.anchor1 && sourceContext) { + // DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => dockingFunc(sourceContext!)); + // console.log("2") + // } + // else if (DocumentManager.Instance.getDocumentView(jumpToDoc)) { + // DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, undefined, undefined, NumCast((this.props.destinationDoc === self.props.linkDoc.anchor2 ? self.props.linkDoc.anchor2Page : self.props.linkDoc.anchor1Page))); + // console.log("3") + + // } + // else { + // DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, dockingFunc); + // console.log("4") + + // } + // } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 11d2743b553da47da88e77de1ac758e16e09b3e0 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Wed, 21 Aug 2019 13:55:46 -0400 Subject: adding docs works --- src/client/views/linking/LinkFollowBox.tsx | 3 ++- src/client/views/linking/LinkMenuItem.tsx | 26 ++++++++++++++------------ src/client/views/nodes/FormattedTextBox.tsx | 2 +- 3 files changed, 17 insertions(+), 14 deletions(-) (limited to 'src/client/views/linking/LinkMenuItem.tsx') diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx index 487281d50..061a4fa93 100644 --- a/src/client/views/linking/LinkFollowBox.tsx +++ b/src/client/views/linking/LinkFollowBox.tsx @@ -1,9 +1,10 @@ import { observable, computed, action, trace } from "mobx"; import React = require("react"); import { observer } from "mobx-react"; -import { FieldViewProps } from "../nodes/FieldView"; +import { FieldViewProps, FieldView } from "../nodes/FieldView"; @observer export class LinkFollowBox extends React.Component { + public static LayoutString() { return FieldView.LayoutString(LinkFollowBox); } } \ No newline at end of file diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 7dc0a9fcd..65516b374 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -1,12 +1,12 @@ import { library } from '@fortawesome/fontawesome-svg-core'; -import { faEdit, faEye, faTimes, faArrowRight, faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons'; +import { faEdit, faEye, faTimes, faArrowRight, faChevronDown, faChevronUp, faGlobeAsia } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { observer } from "mobx-react"; import { DocumentManager } from "../../util/DocumentManager"; import { undoBatch } from "../../util/UndoManager"; import './LinkMenu.scss'; import React = require("react"); -import { Doc, DocListCastAsync } from '../../../new_fields/Doc'; +import { Doc, DocListCastAsync, WidthSym } from '../../../new_fields/Doc'; import { StrCast, Cast, FieldValue, NumCast } from '../../../new_fields/Types'; import { observable, action } from 'mobx'; import { LinkManager } from '../../util/LinkManager'; @@ -138,27 +138,29 @@ export class LinkMenuItem extends React.Component { SelectionManager.DeselectAll(); } + // DONE // this will open a link next to the source doc @undoBatch openLinkInPlace = () => { this.highlightDoc(); let alias = Doc.MakeAlias(this.props.destinationDoc); - let y = this.props.sourceDoc.y; - let x = this.props.sourceDoc.x; - let parentView: any = undefined; - let parentDoc: Doc = this.props.sourceDoc; + let y = NumCast(this.props.sourceDoc.y); + let x = NumCast(this.props.sourceDoc.x); + + let width = NumCast(this.props.sourceDoc.width); + let height = NumCast(this.props.sourceDoc.height); + + alias.x = x + width + 30; + alias.y = y; + alias.width = width; + alias.height = height; SelectionManager.SelectedDocuments().map(dv => { if (dv.props.Document === this.props.sourceDoc) { - parentView = dv.props.ContainingCollectionView; + dv.props.addDocument && dv.props.addDocument(alias, false); } }); - - if (parentView) { - // console.log(parentDoc) - console.log(parentView.props.addDocument); - } } //set this to be the default link behavior, can be any of the above diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 9ae092bad..9652a3a78 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -739,7 +739,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe @action tryUpdateHeight() { if (this.props.Document.autoHeight && this._ref.current!.scrollHeight !== 0) { - console.log("DT = " + this.props.Document.title + " " + this._ref.current!.clientHeight + " " + this._ref.current!.scrollHeight + " " + this._ref.current!.textContent); + // console.log("DT = " + this.props.Document.title + " " + this._ref.current!.clientHeight + " " + this._ref.current!.scrollHeight + " " + this._ref.current!.textContent); let xf = this._ref.current!.getBoundingClientRect(); let scrBounds = this.props.ScreenToLocalTransform().transformBounds(0, 0, xf.width, this._ref.current!.textContent === "" ? 35 : this._ref.current!.scrollHeight); let nh = this.props.Document.isTemplate ? 0 : NumCast(this.dataDoc.nativeHeight, 0); -- cgit v1.2.3-70-g09d2 From 5c9f40006aa157c58ec40828ebd4845c16daa8af Mon Sep 17 00:00:00 2001 From: monikahedman Date: Wed, 21 Aug 2019 15:08:39 -0400 Subject: start of making link follow --- src/client/documents/DocumentTypes.ts | 1 + src/client/documents/Documents.ts | 4 + src/client/views/MainView.tsx | 11 ++ src/client/views/linking/LinkFollowBox.scss | 6 + src/client/views/linking/LinkFollowBox.tsx | 148 ++++++++++++++++++++++++ src/client/views/linking/LinkMenuItem.tsx | 12 +- src/client/views/nodes/DocumentContentsView.tsx | 4 +- 7 files changed, 179 insertions(+), 7 deletions(-) create mode 100644 src/client/views/linking/LinkFollowBox.scss (limited to 'src/client/views/linking/LinkMenuItem.tsx') 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 ?
: null,
+
]; @@ -564,6 +574,7 @@ export class MainView extends React.Component { + {/* */} ); } 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 { 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 ( +
+ +
+ ); + } } \ 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 { // 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 { // 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; @@ -108,7 +110,7 @@ export class DocumentContentsView extends React.Component Date: Thu, 22 Aug 2019 19:42:54 -0400 Subject: making the box come up --- src/client/documents/Documents.ts | 4 ++ src/client/views/MainView.tsx | 2 + src/client/views/linking/LinkFollowBox.scss | 2 +- src/client/views/linking/LinkFollowBox.tsx | 87 ++++++++++++++++++----------- src/client/views/linking/LinkMenuItem.tsx | 12 +++- 5 files changed, 73 insertions(+), 34 deletions(-) (limited to 'src/client/views/linking/LinkMenuItem.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index cd612aaa9..b7c8f4c12 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -446,6 +446,10 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.DRAGBOX), undefined, { ...(options || {}) }); } + export function LinkFollowBoxDocument(options?: DocumentOptions) { + return InstanceFromProto(Prototypes.get(DocumentType.LINKFOLLOW), undefined, { ...(options || {}) }); + } + export function DockDocument(documents: Array, config: string, options: DocumentOptions, id?: string) { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, viewType: CollectionViewType.Docking, dockingConfig: config }, id); } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index f3c8a176c..79c44ae72 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -443,6 +443,7 @@ export class MainView extends React.Component { let imgurl = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg"; let addColNode = action(() => Docs.Create.FreeformDocument([], { width: this.pwidth * .7, height: this.pheight, title: "a freeform collection" })); + let addLinkFollowBox = action(() => Docs.Create.LinkFollowBoxDocument({ width: 200, height: 500, title: "Link Follow Document" })); let addPresNode = action(() => Doc.UserDoc().curPresentation = Docs.Create.PresDocument(new List(), { width: 200, height: 500, title: "a presentation trail" })); let addWebNode = action(() => Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" })); let addDragboxNode = action(() => Docs.Create.DragboxDocument({ width: 40, height: 40, title: "drag collection" })); @@ -458,6 +459,7 @@ export class MainView extends React.Component { [React.createRef(), "globe-asia", "Add Website", addWebNode], [React.createRef(), "bolt", "Add Button", addButtonDocument], [React.createRef(), "file", "Add Document Dragger", addDragboxNode], + [React.createRef(), "caret-up", "Open Link Follow Box", addLinkFollowBox], [React.createRef(), "cloud-upload-alt", "Import Directory", addImportCollectionNode], //remove at some point in favor of addImportCollectionNode //[React.createRef(), "play", "Add Youtube Searcher", addYoutubeSearcher], ]; diff --git a/src/client/views/linking/LinkFollowBox.scss b/src/client/views/linking/LinkFollowBox.scss index c764b002f..522191792 100644 --- a/src/client/views/linking/LinkFollowBox.scss +++ b/src/client/views/linking/LinkFollowBox.scss @@ -2,5 +2,5 @@ .linkFollowBox-main { position: absolute; - background: $main-accent; + background: red; } \ No newline at end of file diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx index 7fc4449d3..247b67776 100644 --- a/src/client/views/linking/LinkFollowBox.tsx +++ b/src/client/views/linking/LinkFollowBox.tsx @@ -9,13 +9,22 @@ import { CollectionViewType } from "../collections/CollectionBaseView"; import { CollectionDockingView } from "../collections/CollectionDockingView"; import { SelectionManager } from "../../util/SelectionManager"; import { DocumentManager } from "../../util/DocumentManager"; +import { DocumentView } from "../nodes/DocumentView"; +import "./LinkFollowBox.scss"; + +export type LinkParamOptions = { + container: Doc; + context: Doc; + sourceDoc: Doc; + shoudldZoom: boolean; + linkDoc: Doc; +}; @observer export class LinkFollowBox extends React.Component { 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(); @@ -31,19 +40,32 @@ export class LinkFollowBox extends React.Component { }, 10000); } + // DONE + @undoBatch + openFullScreen = (destinationDoc: Doc) => { + let view: DocumentView | null = DocumentManager.Instance.getDocumentView(destinationDoc) + view && CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(view); + } + + // should container be a doc or documentview or what? This one needs work and is more long term + @undoBatch + openInContainer = (destinationDoc: Doc, options: { container: Doc }) => { + + } + // 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) { + openLinkColRight = (destinationDoc: Doc, options: { context: Doc }) => { + options.context = Doc.IsPrototype(options.context) ? Doc.MakeDelegate(options.context) : options.context; + if (NumCast(options.context.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; + options.context.panX = newPanX; + options.context.panY = newPanY; } - CollectionDockingView.Instance.AddRightSplit(col, undefined); + CollectionDockingView.Instance.AddRightSplit(options.context, undefined); } // DONE @@ -60,39 +82,39 @@ export class LinkFollowBox extends React.Component { // this is the standard "follow link" (jump to document) // taken from follow link @undoBatch - jumpToLink = async (destinationDoc: Doc, shouldZoom: boolean, linkDoc: Doc) => { + jumpToLink = async (destinationDoc: Doc, options: { shouldZoom: boolean, linkDoc: Doc }) => { //there is an issue right now so this will be false automatically - shouldZoom = false; + options.shouldZoom = false; this.highlightDoc(destinationDoc); let jumpToDoc = destinationDoc; let pdfDoc = FieldValue(Cast(destinationDoc, Doc)); if (pdfDoc) { jumpToDoc = pdfDoc; } - let proto = Doc.GetProto(linkDoc); + let proto = Doc.GetProto(options.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); + if (destinationDoc === options.linkDoc.anchor2 && targetContext) { + DocumentManager.Instance.jumpToDocument(jumpToDoc, options.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 (destinationDoc === options.linkDoc.anchor1 && sourceContext) { + DocumentManager.Instance.jumpToDocument(jumpToDoc, options.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))); + DocumentManager.Instance.jumpToDocument(jumpToDoc, options.shouldZoom, undefined, undefined, NumCast((destinationDoc === options.linkDoc.anchor2 ? options.linkDoc.anchor2Page : options.linkDoc.anchor1Page))); } else { - DocumentManager.Instance.jumpToDocument(jumpToDoc, shouldZoom, false, dockingFunc); + DocumentManager.Instance.jumpToDocument(jumpToDoc, options.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? + // this opens it full screen in new tab @undoBatch openLinkTab = (destinationDoc: Doc) => { this.highlightDoc(destinationDoc); @@ -106,32 +128,32 @@ export class LinkFollowBox extends React.Component { // col = collection the doc is in // target = the document to center on @undoBatch - openLinkColTab = (destinationDoc: Doc, col: Doc) => { + openLinkColTab = (destinationDoc: Doc, options: { context: Doc }) => { this.highlightDoc(destinationDoc); - col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col; - if (NumCast(col.viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) { + options.context = Doc.IsPrototype(options.context) ? Doc.MakeDelegate(options.context) : options.context; + if (NumCast(options.context.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; + options.context.panX = newPanX; + options.context.panY = newPanY; } // CollectionDockingView.Instance.AddRightSplit(col, undefined); - this.props.addDocTab(col, undefined, "inTab"); + this.props.addDocTab(options.context, undefined, "inTab"); SelectionManager.DeselectAll(); } // DONE // this will open a link next to the source doc @undoBatch - openLinkInPlace = (destinationDoc: Doc, sourceDoc: Doc) => { + openLinkInPlace = (destinationDoc: Doc, options: { sourceDoc: Doc }) => { this.highlightDoc(destinationDoc); let alias = Doc.MakeAlias(destinationDoc); - let y = NumCast(sourceDoc.y); - let x = NumCast(sourceDoc.x); + let y = NumCast(options.sourceDoc.y); + let x = NumCast(options.sourceDoc.x); - let width = NumCast(sourceDoc.width); - let height = NumCast(sourceDoc.height); + let width = NumCast(options.sourceDoc.width); + let height = NumCast(options.sourceDoc.height); alias.x = x + width + 30; alias.y = y; @@ -139,18 +161,19 @@ export class LinkFollowBox extends React.Component { alias.height = height; SelectionManager.SelectedDocuments().map(dv => { - if (dv.props.Document === sourceDoc) { + if (dv.props.Document === options.sourceDoc) { dv.props.addDocument && dv.props.addDocument(alias, false); } }); } - private defaultLinkBehavior: any = this.openLinkInPlace; - private currentLinkBehavior: any = this.defaultLinkBehavior; + //set this to be the default link behavior, can be any of the above + private defaultLinkBehavior: (destinationDoc: Doc, options?: any) => void = this.openLinkInPlace; + private currentLinkBehavior: (destinationDoc: Doc, options?: any) => void = this.defaultLinkBehavior; render() { return ( -
+
); diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 41723030d..60f27c664 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -15,6 +15,7 @@ import { CollectionDockingView } from '../collections/CollectionDockingView'; import { SelectionManager } from '../../util/SelectionManager'; import { CollectionViewType } from '../collections/CollectionBaseView'; import { DocumentView } from '../nodes/DocumentView'; +import { SearchUtil } from '../../util/SearchUtil'; library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp); @@ -63,6 +64,13 @@ export class LinkMenuItem extends React.Component { CollectionDockingView.Instance.AddRightSplit(col, undefined); } + // DONE + @undoBatch + openFullScreen = () => { + let view: DocumentView | null = DocumentManager.Instance.getDocumentView(this.props.destinationDoc); + view && CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(view); + } + // DONE // this opens the linked doc in a right split, NOT in its collection @undoBatch @@ -161,10 +169,12 @@ export class LinkMenuItem extends React.Component { dv.props.addDocument && dv.props.addDocument(alias, false); } }); + + this.jumpToLink(false); } //set this to be the default link behavior, can be any of the above - private defaultLinkBehavior: any = this.openLinkInPlace; + private defaultLinkBehavior: any = this.openLinkTab; onEdit = (e: React.PointerEvent): void => { e.stopPropagation(); -- cgit v1.2.3-70-g09d2 From ed7f9a9cd3255f7b774268cfda35685ddacfe2e9 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Fri, 23 Aug 2019 16:38:27 -0400 Subject: basic menu and setting docs working --- src/client/documents/Documents.ts | 1 + src/client/views/MainView.tsx | 6 +- src/client/views/linking/LinkFollowBox.scss | 77 +++++++++- src/client/views/linking/LinkFollowBox.tsx | 213 +++++++++++++++++++++++----- src/client/views/linking/LinkMenuItem.tsx | 5 +- 5 files changed, 260 insertions(+), 42 deletions(-) (limited to 'src/client/views/linking/LinkMenuItem.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index b7c8f4c12..e903d1e06 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -54,6 +54,7 @@ var path = require('path'); export interface DocumentOptions { x?: number; y?: number; + z?: number; type?: string; width?: number; height?: number; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 79c44ae72..82e3c706a 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -1,5 +1,5 @@ import { IconName, library } from '@fortawesome/fontawesome-svg-core'; -import { faArrowDown, faArrowUp, faBolt, faCaretUp, faCat, faCheck, faClone, faCloudUploadAlt, faCommentAlt, faCut, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faLongArrowAltRight, faMusic, faObjectGroup, faPause, faPenNib, faPlay, faPortrait, faRedoAlt, faThumbtack, faTree, faUndoAlt, faTv } from '@fortawesome/free-solid-svg-icons'; +import { faLink, faArrowDown, faArrowUp, faBolt, faCaretUp, faCat, faCheck, faClone, faCloudUploadAlt, faCommentAlt, faCut, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faLongArrowAltRight, faMusic, faObjectGroup, faPause, faPenNib, faPlay, faPortrait, faRedoAlt, faThumbtack, faTree, faUndoAlt, faTv } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, configure, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; @@ -443,7 +443,7 @@ export class MainView extends React.Component { let imgurl = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg"; let addColNode = action(() => Docs.Create.FreeformDocument([], { width: this.pwidth * .7, height: this.pheight, title: "a freeform collection" })); - let addLinkFollowBox = action(() => Docs.Create.LinkFollowBoxDocument({ width: 200, height: 500, title: "Link Follow Document" })); + let addLinkFollowBox = action(() => Docs.Create.LinkFollowBoxDocument({ width: 500, height: 350, title: "Link Follower" })); let addPresNode = action(() => Doc.UserDoc().curPresentation = Docs.Create.PresDocument(new List(), { width: 200, height: 500, title: "a presentation trail" })); let addWebNode = action(() => Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" })); let addDragboxNode = action(() => Docs.Create.DragboxDocument({ width: 40, height: 40, title: "drag collection" })); @@ -459,7 +459,7 @@ export class MainView extends React.Component { [React.createRef(), "globe-asia", "Add Website", addWebNode], [React.createRef(), "bolt", "Add Button", addButtonDocument], [React.createRef(), "file", "Add Document Dragger", addDragboxNode], - [React.createRef(), "caret-up", "Open Link Follow Box", addLinkFollowBox], + [React.createRef(), "link", "Open Link Follow Box", addLinkFollowBox], [React.createRef(), "cloud-upload-alt", "Import Directory", addImportCollectionNode], //remove at some point in favor of addImportCollectionNode //[React.createRef(), "play", "Add Youtube Searcher", addYoutubeSearcher], ]; diff --git a/src/client/views/linking/LinkFollowBox.scss b/src/client/views/linking/LinkFollowBox.scss index 522191792..aedbfdea4 100644 --- a/src/client/views/linking/LinkFollowBox.scss +++ b/src/client/views/linking/LinkFollowBox.scss @@ -2,5 +2,80 @@ .linkFollowBox-main { position: absolute; - background: red; + background: whitesmoke; + color: grey; + border-radius: 15px; + box-shadow: $intermediate-color 0.2vw 0.2vw 0.4vw; + border: solid #BBBBBBBB 5px; + pointer-events: all; + // overflow: hidden; + + .linkFollowBox-header { + height: 30px; + text-align: center; + text-transform: uppercase; + line-height: 30px; + letter-spacing: 2px; + font-size: 16px; + } + + .linkFollowBox-footer { + height: 50px; + text-align: center; + display: flex; + justify-content: center; + align-items: center; + + button { + background-color: $darker-alt-accent; + // height: 30px; + width: 30%; + // font-size: 18px; + } + } + + .linkFollowBox-content { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + grid-column-gap: 5px; + margin-left: 5px; + margin-right: 5px; + + .linkFollowBox-item { + background-color: $light-color; + width: 100%; + height: 100%; + + .linkFollowBox-itemContent { + padding: 5px; + font-size: 12px; + // line-height: 40px; + overflow: scroll; + + + input[type=radio] { + border: 0px; + // width: 100%; + // height: 20px; + // width: 20px; + margin-right: 5px; + } + } + + .title { + display: flex; + justify-content: center; + align-items: center; + text-transform: uppercase; + color: $light-color; + background-color: $lighter-alt-accent; + width: 100%; + height: 30px; + border-bottom: solid $darker-alt-accent 5px; + font-size: 12px; + text-align: center; + } + } + } + } \ No newline at end of file diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx index 247b67776..8cd26bdec 100644 --- a/src/client/views/linking/LinkFollowBox.tsx +++ b/src/client/views/linking/LinkFollowBox.tsx @@ -1,10 +1,10 @@ -import { observable, computed, action, trace } from "mobx"; +import { observable, computed, action, trace, ObservableMap } 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 { NumCast, FieldValue, Cast, StrCast } from "../../../new_fields/Types"; import { CollectionViewType } from "../collections/CollectionBaseView"; import { CollectionDockingView } from "../collections/CollectionDockingView"; import { SelectionManager } from "../../util/SelectionManager"; @@ -12,19 +12,41 @@ import { DocumentManager } from "../../util/DocumentManager"; import { DocumentView } from "../nodes/DocumentView"; import "./LinkFollowBox.scss"; -export type LinkParamOptions = { - container: Doc; - context: Doc; - sourceDoc: Doc; - shoudldZoom: boolean; - linkDoc: Doc; -}; +enum FollowModes { + OPENTAB = "Open in Tab", + OPENRIGHT = "Open in Right Split", + OPENFULL = "Open Full Screen", + PAN = "Pan to Document", + INPLACE = "Open In Place" +} + +enum FollowOptions { + ZOOM = "zoom", + NOZOOM = "no zoom", +} @observer export class LinkFollowBox extends React.Component { public static LayoutString() { return FieldView.LayoutString(LinkFollowBox); } public static Instance: LinkFollowBox; + @observable static linkDoc: Doc | undefined = undefined; + @observable static destinationDoc: Doc | undefined = undefined; + @observable static sourceDoc: Doc | undefined = undefined; + @observable selectedMode: string = ""; + @observable selectedOption: string = ""; + + constructor(props: FieldViewProps) { + super(props); + LinkFollowBox.Instance = this; + } + + @action + setLinkDocs = (linkDoc: Doc, source: Doc, dest: Doc) => { + LinkFollowBox.linkDoc = linkDoc; + LinkFollowBox.sourceDoc = source; + LinkFollowBox.destinationDoc = dest; + } unhighlight = () => { Doc.UnhighlightAll(); @@ -40,11 +62,11 @@ export class LinkFollowBox extends React.Component { }, 10000); } - // DONE @undoBatch openFullScreen = (destinationDoc: Doc) => { - let view: DocumentView | null = DocumentManager.Instance.getDocumentView(destinationDoc) + let view: DocumentView | null = DocumentManager.Instance.getDocumentView(destinationDoc); view && CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(view); + SelectionManager.DeselectAll(); } // should container be a doc or documentview or what? This one needs work and is more long term @@ -54,8 +76,6 @@ export class LinkFollowBox extends React.Component { } // NOT TESTED - // col = collection the doc is in - // target = the document to center on @undoBatch openLinkColRight = (destinationDoc: Doc, options: { context: Doc }) => { options.context = Doc.IsPrototype(options.context) ? Doc.MakeDelegate(options.context) : options.context; @@ -66,26 +86,22 @@ export class LinkFollowBox extends React.Component { options.context.panY = newPanY; } CollectionDockingView.Instance.AddRightSplit(options.context, undefined); + + this.highlightDoc(destinationDoc); + SelectionManager.DeselectAll(); } - // 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); + this.highlightDoc(destinationDoc); SelectionManager.DeselectAll(); + } - // DONE - // this is the standard "follow link" (jump to document) - // taken from follow link @undoBatch jumpToLink = async (destinationDoc: Doc, options: { shouldZoom: boolean, linkDoc: Doc }) => { - //there is an issue right now so this will be false automatically - options.shouldZoom = false; - this.highlightDoc(destinationDoc); let jumpToDoc = destinationDoc; let pdfDoc = FieldValue(Cast(destinationDoc, Doc)); if (pdfDoc) { @@ -110,26 +126,23 @@ export class LinkFollowBox extends React.Component { else { DocumentManager.Instance.jumpToDocument(jumpToDoc, options.shouldZoom, false, dockingFunc); } + + this.highlightDoc(destinationDoc); + SelectionManager.DeselectAll(); } - // DONE - // opens link in new tab (not in a collection) - // this opens it full screen in new tab @undoBatch openLinkTab = (destinationDoc: Doc) => { - this.highlightDoc(destinationDoc); let fullScreenAlias = Doc.MakeAlias(destinationDoc); this.props.addDocTab(fullScreenAlias, undefined, "inTab"); + + this.highlightDoc(destinationDoc); 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, options: { context: Doc }) => { - this.highlightDoc(destinationDoc); options.context = Doc.IsPrototype(options.context) ? Doc.MakeDelegate(options.context) : options.context; if (NumCast(options.context.viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) { const newPanX = NumCast(destinationDoc.x) + NumCast(destinationDoc.width) / NumCast(destinationDoc.zoomBasis, 1) / 2; @@ -137,16 +150,14 @@ export class LinkFollowBox extends React.Component { options.context.panX = newPanX; options.context.panY = newPanY; } - // CollectionDockingView.Instance.AddRightSplit(col, undefined); this.props.addDocTab(options.context, undefined, "inTab"); + + this.highlightDoc(destinationDoc); SelectionManager.DeselectAll(); } - // DONE - // this will open a link next to the source doc @undoBatch - openLinkInPlace = (destinationDoc: Doc, options: { sourceDoc: Doc }) => { - this.highlightDoc(destinationDoc); + openLinkInPlace = (destinationDoc: Doc, options: { sourceDoc: Doc, linkDoc: Doc }) => { let alias = Doc.MakeAlias(destinationDoc); let y = NumCast(options.sourceDoc.y); @@ -165,16 +176,146 @@ export class LinkFollowBox extends React.Component { dv.props.addDocument && dv.props.addDocument(alias, false); } }); + + this.jumpToLink(destinationDoc, { shouldZoom: false, linkDoc: options.linkDoc }); + + this.highlightDoc(destinationDoc); + SelectionManager.DeselectAll(); } //set this to be the default link behavior, can be any of the above private defaultLinkBehavior: (destinationDoc: Doc, options?: any) => void = this.openLinkInPlace; - private currentLinkBehavior: (destinationDoc: Doc, options?: any) => void = this.defaultLinkBehavior; + // private currentLinkBehavior: (destinationDoc: Doc, options?: any) => void = this.defaultLinkBehavior; + + @computed + get LinkFollowTitle(): string { + if (LinkFollowBox.linkDoc) { + return StrCast(LinkFollowBox.linkDoc.title); + } + return "No Link Selected"; + } + + @action + currentLinkBehavior = () => { + if (this.selectedMode === FollowModes.INPLACE) { + + } + else if (this.selectedMode === FollowModes.OPENFULL) { + + } + else if (this.selectedMode === FollowModes.OPENRIGHT) { + + } + else if (this.selectedMode === FollowModes.OPENTAB) { + + } + else if (this.selectedMode === FollowModes.INPLACE) { + + } + else if (this.selectedMode === FollowModes.PAN) { + + } + else return; + } + + @action + handleModeChange = (e: React.ChangeEvent) => { + let target = e.target as HTMLInputElement; + this.selectedMode = target.value; + } + + @action + handleOptionChange = (e: React.ChangeEvent) => { + let target = e.target as HTMLInputElement; + this.selectedOption = target.value; + } + + @computed + get availableModes() { + return ( +
+
+
+
+
+
+
+ ); + } + + @computed + get contexts() { + return ( +
+ +
+ ); + } render() { return (
+
{this.LinkFollowTitle}
+
+
+
Mode
+
{this.availableModes}
+
+
+
Context
+
+ +
+
+
+
Options
+
+
+
+
+
+ +
); } diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 60f27c664..406429ebf 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -16,6 +16,7 @@ import { SelectionManager } from '../../util/SelectionManager'; import { CollectionViewType } from '../collections/CollectionBaseView'; import { DocumentView } from '../nodes/DocumentView'; import { SearchUtil } from '../../util/SearchUtil'; +import { LinkFollowBox } from './LinkFollowBox'; library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp); @@ -174,7 +175,7 @@ export class LinkMenuItem extends React.Component { } //set this to be the default link behavior, can be any of the above - private defaultLinkBehavior: any = this.openLinkTab; + // private defaultLinkBehavior: any = LinkFollowBox.computeLinkDocs(this.props.linkDoc); onEdit = (e: React.PointerEvent): void => { e.stopPropagation(); @@ -242,7 +243,7 @@ export class LinkMenuItem extends React.Component { {/* Original */} {/*
*/} {/* New */} -
+
LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc)}>
{this._showMore ? this.renderMetadata() : <>} -- cgit v1.2.3-70-g09d2 From accfe9900c0b830ef08db3c70fe4940dd3c8c81e Mon Sep 17 00:00:00 2001 From: monikahedman Date: Mon, 26 Aug 2019 10:43:19 -0400 Subject: open in place working --- src/client/views/linking/LinkFollowBox.tsx | 27 ++++++++++++++++++--------- src/client/views/linking/LinkMenuItem.tsx | 4 +++- 2 files changed, 21 insertions(+), 10 deletions(-) (limited to 'src/client/views/linking/LinkMenuItem.tsx') diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx index 5cf14cf58..35b4deeac 100644 --- a/src/client/views/linking/LinkFollowBox.tsx +++ b/src/client/views/linking/LinkFollowBox.tsx @@ -1,4 +1,4 @@ -import { observable, computed, action, trace, ObservableMap, runInAction, reaction } from "mobx"; +import { observable, computed, action, trace, ObservableMap, runInAction, reaction, IReactionDisposer } from "mobx"; import React = require("react"); import { observer } from "mobx-react"; import { FieldViewProps, FieldView } from "../nodes/FieldView"; @@ -43,6 +43,7 @@ export class LinkFollowBox extends React.Component { @observable sourceView: DocumentView | undefined = undefined; @observable canPan: boolean = false; @observable shouldUseOnlyParentContext = false; + _panDisposer?: IReactionDisposer; @observable private _docs: { col: Doc, target: Doc }[] = []; @observable private _otherDocs: { col: Doc, target: Doc }[] = []; @@ -55,7 +56,7 @@ export class LinkFollowBox extends React.Component { componentDidMount = () => { this.resetVars(); - reaction( + this._panDisposer = reaction( () => LinkFollowBox.destinationDoc, async newLinkDestination => { if (LinkFollowBox.destinationDoc && this.sourceView && this.sourceView.props.ContainingCollectionView) { @@ -75,6 +76,10 @@ export class LinkFollowBox extends React.Component { ); } + componentWillUnmount = () => { + this._panDisposer && this._panDisposer(); + } + @action resetVars = () => { this.selectedContext = undefined; @@ -249,6 +254,7 @@ export class LinkFollowBox extends React.Component { if (LinkFollowBox.destinationDoc && LinkFollowBox.sourceDoc) { let alias = Doc.MakeAlias(LinkFollowBox.destinationDoc); + console.log(alias) let y = NumCast(LinkFollowBox.sourceDoc.y); let x = NumCast(LinkFollowBox.sourceDoc.x); @@ -260,13 +266,11 @@ export class LinkFollowBox extends React.Component { alias.width = width; alias.height = height; - SelectionManager.SelectedDocuments().map(dv => { - if (dv.props.Document === LinkFollowBox.sourceDoc) { - dv.props.addDocument && dv.props.addDocument(alias, false); - } - }); + if (this.sourceView && this.sourceView.props.addDocument) { + this.sourceView.props.addDocument(alias, false); + } - this.jumpToLink({ shouldZoom: false }); + this.jumpToLink({ shouldZoom: options.shouldZoom }); this.highlightDoc(); SelectionManager.DeselectAll(); @@ -279,8 +283,13 @@ export class LinkFollowBox extends React.Component { @action currentLinkBehavior = () => { - if (this.selectedMode === FollowModes.INPLACE) { + let shouldZoom: boolean | undefined = this.selectedOption === "" ? undefined : + this.selectedOption === FollowOptions.NOZOOM ? false : true; + if (this.selectedMode === FollowModes.INPLACE) { + console.log("hello") + console.log(shouldZoom) + if (shouldZoom !== undefined) this.openLinkInPlace({ shouldZoom: shouldZoom }); } else if (this.selectedMode === FollowModes.OPENFULL) { diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 406429ebf..d2dc3f7ff 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -175,7 +175,7 @@ export class LinkMenuItem extends React.Component { } //set this to be the default link behavior, can be any of the above - // private defaultLinkBehavior: any = LinkFollowBox.computeLinkDocs(this.props.linkDoc); + private defaultLinkBehavior: any = this.openLinkInPlace; onEdit = (e: React.PointerEvent): void => { e.stopPropagation(); @@ -244,6 +244,8 @@ export class LinkMenuItem extends React.Component { {/*
*/} {/* New */}
LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc)}>
+ {/*
*/} + {this._showMore ? this.renderMetadata() : <>} -- cgit v1.2.3-70-g09d2 From 9c116867bb73b7d84654d9e56688ebd8a982462e Mon Sep 17 00:00:00 2001 From: monikahedman Date: Tue, 27 Aug 2019 17:45:20 -0400 Subject: about to make big changes --- src/client/views/MainView.tsx | 19 ++- src/client/views/linking/LinkFollowBox.scss | 23 +++ src/client/views/linking/LinkFollowBox.tsx | 28 +++- src/client/views/linking/LinkMenuItem.tsx | 214 ++++------------------------ 4 files changed, 77 insertions(+), 207 deletions(-) (limited to 'src/client/views/linking/LinkMenuItem.tsx') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index b49274e7e..d580925d6 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -57,8 +57,6 @@ 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(() => { @@ -437,17 +435,16 @@ export class MainView extends React.Component { } } - toggleLinkFollowBox = () => { + toggleLinkFollowBox = (shouldClose: boolean) => { if (LinkFollowBox.Instance) { - console.log("is instance!") - // if (LinkFollowBox.Instance.props && LinkFollowBox.Instance.props.removeDocument) LinkFollowBox.Instance.props.removeDocument(LinkFollowBox.Instance.props.Document); + let dvs = DocumentManager.Instance.getDocumentViews(LinkFollowBox.Instance.props.Document); + // if it already exisits, close it + if (dvs.length > 0 && shouldClose) LinkFollowBox.Instance.close(); + // open it if not + else Doc.AddDocToList(Cast(CurrentUserUtils.UserDocument.overlays, Doc) as Doc, "data", LinkFollowBox.Instance.props.Document); } else { - let overlayView = document.getElementById("overlayView"); - let overlayWidth = 0; - if (overlayView) overlayWidth = overlayView.offsetWidth; - let x: number = overlayWidth - 500; - let doc = Docs.Create.LinkFollowBoxDocument({ x: x, y: 20, width: 500, height: 370, title: "Link Follower" }); + let doc = Docs.Create.LinkFollowBoxDocument({ x: this.flyoutWidth, y: 20, width: 500, height: 370, title: "Link Follower" }); Doc.AddDocToList(Cast(CurrentUserUtils.UserDocument.overlays, Doc) as Doc, "data", doc); } } @@ -495,7 +492,7 @@ export class MainView extends React.Component { )} -
  • +
  • +