diff options
| author | bobzel <zzzman@gmail.com> | 2023-04-05 22:44:03 -0400 |
|---|---|---|
| committer | bobzel <zzzman@gmail.com> | 2023-04-05 22:44:03 -0400 |
| commit | 9b41da1af16b982ee8ac2fc09f2f8b5d67eac9fb (patch) | |
| tree | bc3f57cd5b31fd453d272c925f6d5b728ab63bae /src/client/views/nodes/DocumentLinksButton.tsx | |
| parent | 9dae453967183b294bf4f7444b948023a1d52d39 (diff) | |
| parent | 8f7e99641f84ad15f34ba9e4a60b664ac93d2e5d (diff) | |
Merge branch 'master' into data-visualization-view-naafi
Diffstat (limited to 'src/client/views/nodes/DocumentLinksButton.tsx')
| -rw-r--r-- | src/client/views/nodes/DocumentLinksButton.tsx | 131 |
1 files changed, 38 insertions, 93 deletions
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index a37de7f69..df3299eef 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -4,19 +4,19 @@ import { action, computed, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { Doc, Opt } from '../../../fields/Doc'; import { StrCast } from '../../../fields/Types'; -import { TraceMobx } from '../../../fields/util'; -import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../Utils'; +import { emptyFunction, returnFalse, setupMoveUpEvents, StopEvent } from '../../../Utils'; import { DocUtils } from '../../documents/Documents'; import { DragManager } from '../../util/DragManager'; import { Hypothesis } from '../../util/HypothesisUtils'; import { LinkManager } from '../../util/LinkManager'; import { undoBatch, UndoManager } from '../../util/UndoManager'; -import { Colors } from '../global/globalEnums'; import './DocumentLinksButton.scss'; import { DocumentView } from './DocumentView'; import { LinkDescriptionPopup } from './LinkDescriptionPopup'; import { TaskCompletionBox } from './TaskCompletedBox'; import React = require('react'); +import _ = require('lodash'); +import { PinProps } from './trails'; const higflyout = require('@hig/flyout'); export const { anchorPoints } = higflyout; @@ -24,10 +24,12 @@ export const Flyout = higflyout.default; interface DocumentLinksButtonProps { View: DocumentView; - Offset?: (number | undefined)[]; + Bottom?: boolean; AlwaysOn?: boolean; InMenu?: boolean; + OnHover?: boolean; StartLink?: boolean; //whether the link HAS been started (i.e. now needs to be completed) + ShowCount?: boolean; scaling?: () => number; // how uch doc is scaled so that link buttons can invert it } @observer @@ -39,9 +41,6 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp @observable public static AnnotationUri: string | undefined; @observable public static LinkEditorDocView: DocumentView | undefined; - @observable public static invisibleWebDoc: Opt<Doc>; - public static invisibleWebRef = React.createRef<HTMLDivElement>(); - @action @undoBatch onLinkButtonMoved = (e: PointerEvent) => { @@ -72,11 +71,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp e, this.onLinkButtonMoved, emptyFunction, - action((e, doubleTap) => { - if (doubleTap) { - DocumentView.showBackLinks(this.props.View.rootDoc); - } - }), + action((e, doubleTap) => doubleTap && DocumentView.showBackLinks(this.props.View.rootDoc)), undefined, undefined, action(() => (DocumentLinksButton.LinkEditorDocView = this.props.View)) @@ -119,7 +114,6 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp DocumentLinksButton.StartLink = this.props.View.props.Document; DocumentLinksButton.StartLinkView = this.props.View; } - //action(() => Doc.BrushDoc(this.props.View.Document)); } }; @@ -130,55 +124,15 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp returnFalse, emptyFunction, undoBatch( - action((e, doubleTap) => { - if (doubleTap && !this.props.StartLink) { - if (DocumentLinksButton.StartLink === this.props.View.props.Document) { - DocumentLinksButton.StartLink = undefined; - DocumentLinksButton.StartLinkView = undefined; - DocumentLinksButton.AnnotationId = undefined; - } else if (DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document) { - const sourceDoc = DocumentLinksButton.StartLink; - const targetDoc = this.props.View.ComponentView?.getAnchor?.() || this.props.View.Document; - const linkDoc = DocUtils.MakeLink({ doc: sourceDoc }, { doc: targetDoc }, 'links'); //why is long drag here when this is used for completing links by clicking? - - LinkManager.currentLink = linkDoc; - - runInAction(() => { - if (linkDoc) { - TaskCompletionBox.textDisplayed = 'Link Created'; - TaskCompletionBox.popupX = e.screenX; - TaskCompletionBox.popupY = e.screenY - 133; - TaskCompletionBox.taskCompleted = true; - - LinkDescriptionPopup.popupX = e.screenX; - LinkDescriptionPopup.popupY = e.screenY - 100; - LinkDescriptionPopup.descriptionPopup = true; - - const rect = document.body.getBoundingClientRect(); - if (LinkDescriptionPopup.popupX + 200 > rect.width) { - LinkDescriptionPopup.popupX -= 190; - TaskCompletionBox.popupX -= 40; - } - if (LinkDescriptionPopup.popupY + 100 > rect.height) { - LinkDescriptionPopup.popupY -= 40; - TaskCompletionBox.popupY -= 40; - } - - setTimeout( - action(() => (TaskCompletionBox.taskCompleted = false)), - 2500 - ); - } - }); - } - } + action(e => { + DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this.props.View.props.Document, true, this.props.View); }) ) ); }; public static finishLinkClick = undoBatch( - action((screenX: number, screenY: number, startLink: Doc, endLink: Doc, startIsAnnotation: boolean, endLinkView?: DocumentView) => { + action((screenX: number, screenY: number, startLink: Doc, endLink: Doc, startIsAnnotation: boolean, endLinkView?: DocumentView, pinProps?: PinProps) => { if (startLink === endLink) { DocumentLinksButton.StartLink = undefined; DocumentLinksButton.StartLinkView = undefined; @@ -186,9 +140,9 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp DocumentLinksButton.AnnotationUri = undefined; //!this.props.StartLink } else if (startLink !== endLink) { - endLink = endLinkView?.docView?._componentView?.getAnchor?.() || endLink; - startLink = DocumentLinksButton.StartLinkView?.docView?._componentView?.getAnchor?.() || startLink; - const linkDoc = DocUtils.MakeLink({ doc: startLink }, { doc: endLink }, DocumentLinksButton.AnnotationId ? 'hypothes.is annotation' : undefined, undefined, undefined, true); + endLink = endLinkView?.docView?._componentView?.getAnchor?.(true, pinProps) || endLink; + startLink = DocumentLinksButton.StartLinkView?.docView?._componentView?.getAnchor?.(true) || startLink; + const linkDoc = DocUtils.MakeLink(startLink, endLink, { linkRelationship: DocumentLinksButton.AnnotationId ? 'hypothes.is annotation' : undefined }, undefined, true); LinkManager.currentLink = linkDoc; @@ -256,38 +210,33 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp * todo:glr / anh seperate functionality such as onClick onPointerDown of link menu button */ @computed get linkButtonInner() { - const btnDim = '30px'; - const link = <img style={{ width: '22px', height: '16px' }} src={`/assets/${'link.png'}`} />; + const btnDim = 30; const isActive = DocumentLinksButton.StartLink === this.props.View.props.Document && this.props.StartLink; - return !this.props.InMenu ? ( - <div className="documentLinksButton-cont" style={{ left: this.props.Offset?.[0], top: this.props.Offset?.[1], right: this.props.Offset?.[2], bottom: this.props.Offset?.[3] }}> - <div - className={'documentLinksButton'} - onPointerDown={this.onLinkMenuOpen} - onClick={this.onLinkClick} - style={{ - backgroundColor: Colors.LIGHT_BLUE, - color: Colors.BLACK, - fontSize: '20px', - width: btnDim, - height: btnDim, - }}> - {Array.from(this.filteredLinks).length} - </div> + const scaling = Math.min(1, this.props.scaling?.() || 1); + const showLinkCount = (onHover?: boolean, offset?: boolean) => ( + <div + className="documentLinksButton-showCount" + onPointerDown={this.onLinkMenuOpen} + style={{ + fontSize: (onHover ? btnDim / 2 : 20) * scaling, + width: (onHover ? btnDim / 2 : btnDim) * scaling, + height: (onHover ? btnDim / 2 : btnDim) * scaling, + bottom: offset ? 5 * scaling : onHover ? (-btnDim / 2) * scaling : undefined, + }}> + <span style={{ width: '100%', display: 'inline-block', textAlign: 'center' }}>{Array.from(this.filteredLinks).length}</span> </div> + ); + return this.props.ShowCount ? ( + showLinkCount(this.props.OnHover, this.props.Bottom) ) : ( <div className="documentLinksButton-menu"> - {this.props.InMenu && !this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document ? ( //if the origin node is not this node - <div - className={'documentLinksButton-endLink'} - ref={this._linkButton} - onPointerDown={DocumentLinksButton.StartLink && this.completeLink} - onClick={e => DocumentLinksButton.StartLink && DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this.props.View.props.Document, true, this.props.View)}> + {this.props.StartLink ? ( //if link has been started from current node, then set behavior of link button to deactivate linking when clicked again + <div className={`documentLinksButton ${isActive ? `startLink` : ``}`} ref={this._linkButton} onPointerDown={isActive ? StopEvent : this.onLinkButtonDown} onClick={isActive ? this.clearLinks : this.onLinkClick}> <FontAwesomeIcon className="documentdecorations-icon" icon="link" /> </div> ) : null} - {this.props.InMenu && this.props.StartLink ? ( //if link has been started from current node, then set behavior of link button to deactivate linking when clicked again - <div className={`documentLinksButton ${isActive ? `startLink` : ``}`} ref={this._linkButton} onPointerDown={isActive ? undefined : this.onLinkButtonDown} onClick={isActive ? this.clearLinks : this.onLinkClick}> + {!this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document ? ( //if the origin node is not this node + <div className={'documentLinksButton-endLink'} ref={this._linkButton} onPointerDown={DocumentLinksButton.StartLink && this.completeLink}> <FontAwesomeIcon className="documentdecorations-icon" icon="link" /> </div> ) : null} @@ -296,24 +245,20 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp } render() { - TraceMobx(); - const menuTitle = this.props.StartLink ? 'Drag or tap to start link' : 'Tap to complete link'; const buttonTitle = 'Tap to view links; double tap to open link collection'; - const title = this.props.InMenu ? menuTitle : buttonTitle; + const title = this.props.ShowCount ? buttonTitle : menuTitle; //render circular tooltip if it isn't set to invisible and show the number of doc links the node has, and render inner-menu link button for starting/stopping links if currently in menu return !Array.from(this.filteredLinks).length && !this.props.AlwaysOn ? null : ( <div className="documentLinksButton-wrapper" style={{ - transform: `scale(${this.props.scaling?.() || 1})`, + position: this.props.InMenu ? 'relative' : 'absolute', + top: 0, + pointerEvents: 'none', }}> - {(this.props.InMenu && (DocumentLinksButton.StartLink || this.props.StartLink)) || (!DocumentLinksButton.LinkEditorDocView && !this.props.InMenu) ? ( - <Tooltip title={<div className="dash-tooltip">{title}</div>}>{this.linkButtonInner}</Tooltip> - ) : ( - this.linkButtonInner - )} + {DocumentLinksButton.LinkEditorDocView ? this.linkButtonInner : <Tooltip title={<div className="dash-tooltip">{title}</div>}>{this.linkButtonInner}</Tooltip>} </div> ); } |
