diff options
-rw-r--r-- | src/client/views/MainView.tsx | 19 | ||||
-rw-r--r-- | src/client/views/linking/LinkFollowBox.scss | 23 | ||||
-rw-r--r-- | src/client/views/linking/LinkFollowBox.tsx | 28 | ||||
-rw-r--r-- | src/client/views/linking/LinkMenuItem.tsx | 214 |
4 files changed, 77 insertions, 207 deletions
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 { <FontAwesomeIcon icon={btn[1]} size="sm" /> </button> </div></li>)} - <li key="linkFollow"><button className="add-button round-button" title="Open Link Follower" onClick={this.toggleLinkFollowBox}><FontAwesomeIcon icon="link" size="sm" /></button></li> + <li key="linkFollow"><button className="add-button round-button" title="Open Link Follower" onClick={() => this.toggleLinkFollowBox(true)}><FontAwesomeIcon icon="link" size="sm" /></button></li> <li key="color"><button className="add-button round-button" title="Select Color" style={{ zIndex: 1000 }} onClick={() => this.toggleColorPicker()}><div className="toolbar-color-button" style={{ backgroundColor: InkingControl.Instance.selectedColor }} > <div className="toolbar-color-picker" onClick={this.onColorClick} style={this._colorPickerDisplay ? { color: "black", display: "block" } : { color: "black", display: "none" }}> <SketchPicker color={InkingControl.Instance.selectedColor} onChange={InkingControl.Instance.switchColor} /> diff --git a/src/client/views/linking/LinkFollowBox.scss b/src/client/views/linking/LinkFollowBox.scss index a34285727..e425bde69 100644 --- a/src/client/views/linking/LinkFollowBox.scss +++ b/src/client/views/linking/LinkFollowBox.scss @@ -18,12 +18,35 @@ // line-height: 30px; letter-spacing: 2px; font-size: 16px; + width: 100%; } .direction-indicator { font-size: 12px; } + .closeDocument { + position: relative; + // z-index: inherit; + max-width: 30px; + top: -20px; + // left: 230px; + left: 460px; + color: $darker-alt-accent // right: 5px; + } + + .closeDocument:hover { + color: $main-accent; + } + + .topHeader { + // display: grid; + // grid-template-columns: 90% 10%; + width: 100%; + // flex-direction: row; + height: 25px; + } + .linkFollowBox-footer { height: 50px; text-align: center; diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx index cf44ae649..588f48017 100644 --- a/src/client/views/linking/LinkFollowBox.tsx +++ b/src/client/views/linking/LinkFollowBox.tsx @@ -2,7 +2,7 @@ import { observable, computed, action, trace, ObservableMap, runInAction, reacti import React = require("react"); import { observer } from "mobx-react"; import { FieldViewProps, FieldView } from "../nodes/FieldView"; -import { Doc } from "../../../new_fields/Doc"; +import { Doc, DocListCastAsync } from "../../../new_fields/Doc"; import { undoBatch } from "../../util/UndoManager"; import { NumCast, FieldValue, Cast, StrCast } from "../../../new_fields/Types"; import { CollectionViewType } from "../collections/CollectionBaseView"; @@ -17,6 +17,9 @@ import { listSpec } from "../../../new_fields/Schema"; import { DocServer } from "../../DocServer"; import { RefField } from "../../../new_fields/RefField"; import { Docs } from "../../documents/Documents"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faTimes } from '@fortawesome/free-solid-svg-icons'; +import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; enum FollowModes { OPENTAB = "Open in Tab", @@ -48,7 +51,6 @@ export class LinkFollowBox extends React.Component<FieldViewProps> { @observable canPan: boolean = false; @observable shouldUseOnlyParentContext = false; _contextDisposer?: IReactionDisposer; - collectionTypes: string[]; @observable private _docs: { col: Doc, target: Doc }[] = []; @observable private _otherDocs: { col: Doc, target: Doc }[] = []; @@ -56,8 +58,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> { constructor(props: FieldViewProps) { super(props); LinkFollowBox.Instance = this; - - this.collectionTypes = ["Invalid", "Freeform", "Schema", "Docking", "Tree", "Stacking", "Masonry"]; + this.props.Document.isBackground = true; } @computed @@ -322,7 +323,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> { } //set this to be the default link behavior, can be any of the above - private defaultLinkBehavior: (options?: any) => void = this.openLinkInPlace; + public defaultLinkBehavior: (options?: any) => void = this.openLinkRight; @action currentLinkBehavior = () => { @@ -556,12 +557,20 @@ export class LinkFollowBox extends React.Component<FieldViewProps> { return null; } + async close() { + let res = await DocListCastAsync((CurrentUserUtils.UserDocument.overlays as Doc).data); + if (res) res.splice(res.indexOf(LinkFollowBox.Instance.props.Document), 1); + } + render() { return ( <div className="linkFollowBox-main" style={{ height: NumCast(this.props.Document.height), width: NumCast(this.props.Document.width) }}> <div className="linkFollowBox-header"> - {LinkFollowBox.linkDoc ? "Link Title: " + StrCast(LinkFollowBox.linkDoc.title) : "No Link Selected"} - <div className="linkFollowBox-header direction-indicator">{LinkFollowBox.linkDoc ? + <div className="topHeader"> + {LinkFollowBox.linkDoc ? "Link Title: " + StrCast(LinkFollowBox.linkDoc.title) : "No Link Selected"} + <div onClick={this.close} className="closeDocument"><FontAwesomeIcon icon={faTimes} size="lg" /></div> + </div> + <div className=" direction-indicator">{LinkFollowBox.linkDoc ? LinkFollowBox.sourceDoc && LinkFollowBox.destinationDoc ? "Source: " + StrCast(LinkFollowBox.sourceDoc.title) + ", Destination: " + StrCast(LinkFollowBox.destinationDoc.title) : "" : ""}</div> </div> @@ -587,6 +596,11 @@ export class LinkFollowBox extends React.Component<FieldViewProps> { </div> <div className="linkFollowBox-footer"> <button + onClick={this.resetVars}> + Clear Link + </button> + <div style={{ width: 20 }}></div> + <button onClick={this.currentLinkBehavior} disabled={(LinkFollowBox.linkDoc) ? false : true}> Follow Link diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index d2dc3f7ff..0dda948c4 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -17,6 +17,9 @@ import { CollectionViewType } from '../collections/CollectionBaseView'; import { DocumentView } from '../nodes/DocumentView'; import { SearchUtil } from '../../util/SearchUtil'; import { LinkFollowBox } from './LinkFollowBox'; +import { ContextMenu } from '../ContextMenu'; +import { MainView } from '../MainView'; +import { Docs } from '../../documents/Documents'; library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp); @@ -35,148 +38,6 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { @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: Doc) => { - col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col; - if (NumCast(col.viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) { - 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; - } - 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 - 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: Doc) => { - this.highlightDoc(); - col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col; - if (NumCast(col.viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) { - 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; - } - // 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 = () => { - this.highlightDoc(); - - let alias = Doc.MakeAlias(this.props.destinationDoc); - 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) { - 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; - onEdit = (e: React.PointerEvent): void => { e.stopPropagation(); this.props.showEditor(this.props.linkDoc); @@ -226,6 +87,26 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { e.stopPropagation(); } + onContextMenu = (e: React.MouseEvent) => { + e.preventDefault(); + ContextMenu.Instance.addItem({ description: "Open in Link Follower", event: () => console.log("opening 1!"), icon: "link" }); + ContextMenu.Instance.addItem({ description: "Follow Default Link", event: () => this.followDefault(), icon: "arrow-right" }); + ContextMenu.Instance.displayMenu(e.clientX, e.clientY); + } + + followDefault = () => { + if (!LinkFollowBox.Instance) { + Docs.Create.LinkFollowBoxDocument({ x: MainView.Instance.flyoutWidth, y: 20, width: 500, height: 370, title: "Link Follower" }); + } + LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc); + LinkFollowBox.Instance.defaultLinkBehavior(); + } + + openLinkFollower = () => { + LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc); + MainView.Instance.toggleLinkFollowBox(false); + } + render() { let keys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);//groupMetadataKeys.get(this.props.groupType); @@ -240,12 +121,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { {canExpand ? <div title="Show more" className="button" onPointerDown={() => this.toggleShowMore()}> <FontAwesomeIcon className="fa-icon" icon={this._showMore ? "chevron-up" : "chevron-down"} size="sm" /></div> : <></>} <div title="Edit link" className="button" onPointerDown={this.onEdit}><FontAwesomeIcon className="fa-icon" icon="edit" size="sm" /></div> - {/* Original */} - {/* <div title="Follow link" className="button" onPointerDown={this.onFollowLink}><FontAwesomeIcon className="fa-icon" icon="arrow-right" size="sm" /></div> */} - {/* New */} - <div title="Follow link" className="button" onClick={() => LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc)}><FontAwesomeIcon className="fa-icon" icon="arrow-right" size="sm" /></div> - {/* <div title="Follow link" className="button" onClick={this.defaultLinkBehavior}><FontAwesomeIcon className="fa-icon" icon="arrow-right" size="sm" /></div> */} - + <div title="Follow link" className="button" onClick={this.followDefault} onContextMenu={this.onContextMenu}><FontAwesomeIcon className="fa-icon" icon="arrow-right" size="sm" /></div> </div> </div> {this._showMore ? this.renderMetadata() : <></>} @@ -254,44 +130,4 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { </div > ); } -} - - // @undoBatch - // onFollowLink = async (e: React.PointerEvent): Promise<void> => { - // 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 +}
\ No newline at end of file |