diff options
Diffstat (limited to 'src/client/views/linking')
| -rw-r--r-- | src/client/views/linking/LinkEditor.tsx | 346 | ||||
| -rw-r--r-- | src/client/views/linking/LinkMenuItem.tsx | 226 |
2 files changed, 333 insertions, 239 deletions
diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx index 1414bfdf7..ba301962b 100644 --- a/src/client/views/linking/LinkEditor.tsx +++ b/src/client/views/linking/LinkEditor.tsx @@ -1,15 +1,14 @@ -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { Tooltip } from "@material-ui/core"; -import { action, computed, observable } from "mobx"; -import { observer } from "mobx-react"; -import { Doc, NumListCast, StrListCast, Field } from "../../../fields/Doc"; -import { DateCast, StrCast, Cast } from "../../../fields/Types"; -import { LinkManager } from "../../util/LinkManager"; -import { undoBatch } from "../../util/UndoManager"; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Tooltip } from '@material-ui/core'; +import { action, computed, observable } from 'mobx'; +import { observer } from 'mobx-react'; +import { Doc, NumListCast, StrListCast, Field } from '../../../fields/Doc'; +import { DateCast, StrCast, Cast } from '../../../fields/Types'; +import { LinkManager } from '../../util/LinkManager'; +import { undoBatch } from '../../util/UndoManager'; import './LinkEditor.scss'; -import { LinkRelationshipSearch } from "./LinkRelationshipSearch"; -import React = require("react"); - +import { LinkRelationshipSearch } from './LinkRelationshipSearch'; +import React = require('react'); interface LinkEditorProps { sourceDoc: Doc; @@ -19,16 +18,20 @@ interface LinkEditorProps { } @observer export class LinkEditor extends React.Component<LinkEditorProps> { - @observable description = Field.toString(LinkManager.currentLink?.description as any as Field); @observable relationship = StrCast(LinkManager.currentLink?.linkRelationship); @observable zoomFollow = StrCast(this.props.sourceDoc.followLinkZoom); @observable openDropdown: boolean = false; @observable showInfo: boolean = false; - @computed get infoIcon() { if (this.showInfo) { return "chevron-up"; } return "chevron-down"; } - @observable private buttonColor: string = ""; - @observable private relationshipButtonColor: string = ""; - @observable private relationshipSearchVisibility: string = "none"; + @computed get infoIcon() { + if (this.showInfo) { + return 'chevron-up'; + } + return 'chevron-down'; + } + @observable private buttonColor: string = ''; + @observable private relationshipButtonColor: string = ''; + @observable private relationshipSearchVisibility: string = 'none'; @observable private searchIsActive: boolean = false; //@observable description = this.props.linkDoc.description ? StrCast(this.props.linkDoc.description) : "DESCRIPTION"; @@ -37,7 +40,7 @@ export class LinkEditor extends React.Component<LinkEditorProps> { deleteLink = (): void => { LinkManager.Instance.deleteLink(this.props.linkDoc); this.props.showLinks(); - } + }; @undoBatch setRelationshipValue = action((value: string) => { @@ -49,11 +52,11 @@ export class LinkEditor extends React.Component<LinkEditorProps> { const linkRelationshipSizes = NumListCast(Doc.UserDoc().linkRelationshipSizes); const linkColorList = StrListCast(Doc.UserDoc().linkColorList); - // if the relationship does not exist in the list, add it and a corresponding unique randomly generated color + // if the relationship does not exist in the list, add it and a corresponding unique randomly generated color if (!linkRelationshipList?.includes(value)) { linkRelationshipList.push(value); linkRelationshipSizes.push(1); - const randColor = "rgb(" + Math.floor(Math.random() * 255) + "," + Math.floor(Math.random() * 255) + "," + Math.floor(Math.random() * 255) + ")"; + const randColor = 'rgb(' + Math.floor(Math.random() * 255) + ',' + Math.floor(Math.random() * 255) + ',' + Math.floor(Math.random() * 255) + ')'; linkColorList.push(randColor); // if the relationship is already in the list AND the new rel is different from the prev rel, update the rel sizes } else if (linkRelationshipList && value !== prevRelationship) { @@ -61,20 +64,22 @@ export class LinkEditor extends React.Component<LinkEditorProps> { //increment size of new relationship size if (index !== -1 && index < linkRelationshipSizes.length) { const pvalue = linkRelationshipSizes[index]; - linkRelationshipSizes[index] = (pvalue === undefined || !Number.isFinite(pvalue) ? 1 : pvalue + 1); + linkRelationshipSizes[index] = pvalue === undefined || !Number.isFinite(pvalue) ? 1 : pvalue + 1; } //decrement the size of the previous relationship if it already exists (i.e. not default 'link' relationship upon link creation) if (linkRelationshipList.includes(prevRelationship)) { const pindex = linkRelationshipList.indexOf(prevRelationship); if (pindex !== -1 && pindex < linkRelationshipSizes.length) { const pvalue = linkRelationshipSizes[pindex]; - linkRelationshipSizes[pindex] = Math.max(0, (pvalue === undefined || !Number.isFinite(pvalue) ? 1 : pvalue - 1)); + linkRelationshipSizes[pindex] = Math.max(0, pvalue === undefined || !Number.isFinite(pvalue) ? 1 : pvalue - 1); } } - } - this.relationshipButtonColor = "rgb(62, 133, 55)"; - setTimeout(action(() => this.relationshipButtonColor = ""), 750); + this.relationshipButtonColor = 'rgb(62, 133, 55)'; + setTimeout( + action(() => (this.relationshipButtonColor = '')), + 750 + ); return true; } }); @@ -89,144 +94,143 @@ export class LinkEditor extends React.Component<LinkEditorProps> { if (linkRelationshipList) { return linkRelationshipList.filter(rel => rel.includes(query)); } - } + }; /** * toggles visibility of the relationship search results when the input field is focused on */ @action toggleRelationshipResults = () => { - this.relationshipSearchVisibility = this.relationshipSearchVisibility === "none" ? "block" : "none"; - } + this.relationshipSearchVisibility = this.relationshipSearchVisibility === 'none' ? 'block' : 'none'; + }; @undoBatch setDescripValue = action((value: string) => { if (LinkManager.currentLink) { Doc.GetProto(LinkManager.currentLink).description = value; - this.buttonColor = "rgb(62, 133, 55)"; - setTimeout(action(() => this.buttonColor = ""), 750); + this.buttonColor = 'rgb(62, 133, 55)'; + setTimeout( + action(() => (this.buttonColor = '')), + 750 + ); return true; } }); onDescriptionKey = (e: React.KeyboardEvent<HTMLInputElement>) => { - if (e.key === "Enter") { + if (e.key === 'Enter') { this.setDescripValue(this.description); document.getElementById('input')?.blur(); } e.stopPropagation(); - } + }; onRelationshipKey = (e: React.KeyboardEvent<HTMLInputElement>) => { - if (e.key === "Enter") { + if (e.key === 'Enter') { this.setRelationshipValue(this.relationship); document.getElementById('input')?.blur(); } e.stopPropagation(); - } + }; onDescriptionDown = () => this.setDescripValue(this.description); onRelationshipDown = () => this.setRelationshipValue(this.relationship); onBlur = () => { - //only hide the search results if the user clicks out of the input AND not on any of the search results + //only hide the search results if the user clicks out of the input AND not on any of the search results // i.e. if search is not active if (!this.searchIsActive) { this.toggleRelationshipResults(); } - } + }; onFocus = () => { this.toggleRelationshipResults(); - } + }; toggleSearchIsActive = () => { this.searchIsActive = !this.searchIsActive; - } + }; @action - handleDescriptionChange = (e: React.ChangeEvent<HTMLInputElement>) => { this.description = e.target.value; } + handleDescriptionChange = (e: React.ChangeEvent<HTMLInputElement>) => { + this.description = e.target.value; + }; @action - handleRelationshipChange = (e: React.ChangeEvent<HTMLInputElement>) => { this.relationship = e.target.value; } + handleRelationshipChange = (e: React.ChangeEvent<HTMLInputElement>) => { + this.relationship = e.target.value; + }; @action - handleZoomFollowChange = (e: React.ChangeEvent<HTMLInputElement>) => { this.props.sourceDoc.followLinkZoom = e.target.checked; } + handleZoomFollowChange = (e: React.ChangeEvent<HTMLInputElement>) => { + this.props.sourceDoc.followLinkZoom = e.target.checked; + }; @action handleRelationshipSearchChange = (result: string) => { this.setRelationshipValue(result); this.toggleRelationshipResults(); this.relationship = result; - } + }; @computed get editRelationship() { //NOTE: confusingly, the classnames for the following relationship JSX elements are the same as the for the description elements for shared CSS - return <div className="linkEditor-description"> - <div className="linkEditor-description-label">Link Relationship:</div> - <div className="linkEditor-description-input"> - <div className="linkEditor-description-editing"> - <input - style={{ width: "100%" }} - id="input" - value={this.relationship} - autoComplete={"off"} - placeholder={"Enter link relationship"} - onKeyDown={this.onRelationshipKey} - onChange={this.handleRelationshipChange} - onFocus={this.onFocus} - onBlur={this.onBlur} - ></input> - <LinkRelationshipSearch - results={this.getRelationshipResults()} - display={this.relationshipSearchVisibility} - handleRelationshipSearchChange={this.handleRelationshipSearchChange} - toggleSearch={this.toggleSearchIsActive} - /> + return ( + <div className="linkEditor-description"> + <div className="linkEditor-description-label">Link Relationship:</div> + <div className="linkEditor-description-input"> + <div className="linkEditor-description-editing"> + <input + style={{ width: '100%' }} + id="input" + value={this.relationship} + autoComplete={'off'} + placeholder={'Enter link relationship'} + onKeyDown={this.onRelationshipKey} + onChange={this.handleRelationshipChange} + onFocus={this.onFocus} + onBlur={this.onBlur}></input> + <LinkRelationshipSearch results={this.getRelationshipResults()} display={this.relationshipSearchVisibility} handleRelationshipSearchChange={this.handleRelationshipSearchChange} toggleSearch={this.toggleSearchIsActive} /> + </div> + <div className="linkEditor-description-add-button" style={{ background: this.relationshipButtonColor }} onPointerDown={this.onRelationshipDown}> + Set + </div> </div> - <div className="linkEditor-description-add-button" - style={{ background: this.relationshipButtonColor }} - onPointerDown={this.onRelationshipDown}>Set</div> </div> - </div>; + ); } @computed get editZoomFollow() { //NOTE: confusingly, the classnames for the following relationship JSX elements are the same as the for the description elements for shared CSS - return <div className="linkEditor-zoomFollow"> - <div className="linkEditor-zoomFollow-label">Zoom To Link Target:</div> - <div className="linkEditor-zoomFollow-input"> - <div className="linkEditor-zoomFollow-editing"> - <input - style={{ width: "100%" }} - type="checkbox" - value={this.zoomFollow} - onChange={this.handleZoomFollowChange} /> + return ( + <div className="linkEditor-zoomFollow"> + <div className="linkEditor-zoomFollow-label">Zoom To Link Target:</div> + <div className="linkEditor-zoomFollow-input"> + <div className="linkEditor-zoomFollow-editing"> + <input style={{ width: '100%' }} type="checkbox" value={this.zoomFollow} onChange={this.handleZoomFollowChange} /> + </div> </div> </div> - </div >; + ); } @computed get editDescription() { - return <div className="linkEditor-description"> - <div className="linkEditor-description-label">Link Description:</div> - <div className="linkEditor-description-input"> - <div className="linkEditor-description-editing"> - <input - style={{ width: "100%" }} - autoComplete={"off"} - id="input" - value={this.description} - placeholder={"Enter link description"} - onKeyDown={this.onDescriptionKey} - onChange={this.handleDescriptionChange} - ></input> + return ( + <div className="linkEditor-description"> + <div className="linkEditor-description-label">Link Description:</div> + <div className="linkEditor-description-input"> + <div className="linkEditor-description-editing"> + <input style={{ width: '100%' }} autoComplete={'off'} id="input" value={this.description} placeholder={'Enter link description'} onKeyDown={this.onDescriptionKey} onChange={this.handleDescriptionChange}></input> + </div> + <div className="linkEditor-description-add-button" style={{ background: this.buttonColor }} onPointerDown={this.onDescriptionDown}> + Set + </div> </div> - <div className="linkEditor-description-add-button" - style={{ background: this.buttonColor }} - onPointerDown={this.onDescriptionDown}>Set</div> </div> - </div>; + ); } @action - changeDropdown = () => { this.openDropdown = !this.openDropdown; } + changeDropdown = () => { + this.openDropdown = !this.openDropdown; + }; @undoBatch changeFollowBehavior = action((follow: string) => { @@ -236,94 +240,114 @@ export class LinkEditor extends React.Component<LinkEditorProps> { @computed get followingDropdown() { - return <div className="linkEditor-followingDropdown"> - <div className="linkEditor-followingDropdown-label">Follow Behavior:</div> - <div className="linkEditor-followingDropdown-dropdown"> - <div className="linkEditor-followingDropdown-header" - onPointerDown={this.changeDropdown}> - {StrCast(this.props.linkDoc.followLinkLocation, "default")} - <FontAwesomeIcon className="linkEditor-followingDropdown-icon" - icon={this.openDropdown ? "chevron-up" : "chevron-down"} - size={"lg"} /> - </div> - <div className="linkEditor-followingDropdown-optionsList" - style={{ display: this.openDropdown ? "" : "none" }}> - <div className="linkEditor-followingDropdown-option" - onPointerDown={() => this.changeFollowBehavior("default")}> - Default + return ( + <div className="linkEditor-followingDropdown"> + <div className="linkEditor-followingDropdown-label">Follow Behavior:</div> + <div className="linkEditor-followingDropdown-dropdown"> + <div className="linkEditor-followingDropdown-header" onPointerDown={this.changeDropdown}> + {StrCast(this.props.linkDoc.followLinkLocation, 'default')} + <FontAwesomeIcon className="linkEditor-followingDropdown-icon" icon={this.openDropdown ? 'chevron-up' : 'chevron-down'} size={'lg'} /> </div> - <div className="linkEditor-followingDropdown-option" - onPointerDown={() => this.changeFollowBehavior("add:left")}> - Always open in new left pane - </div> - <div className="linkEditor-followingDropdown-option" - onPointerDown={() => this.changeFollowBehavior("add:right")}> - Always open in new right pane - </div> - <div className="linkEditor-followingDropdown-option" - onPointerDown={() => this.changeFollowBehavior("replace:right")}> - Always replace right tab - </div> - <div className="linkEditor-followingDropdown-option" - onPointerDown={() => this.changeFollowBehavior("replace:left")}> - Always replace left tab - </div> - <div className="linkEditor-followingDropdown-option" - onPointerDown={() => this.changeFollowBehavior("fullScreen")}> - Always open full screen - </div> - <div className="linkEditor-followingDropdown-option" - onPointerDown={() => this.changeFollowBehavior("add")}> - Always open in a new tab - </div> - <div className="linkEditor-followingDropdown-option" - onPointerDown={() => this.changeFollowBehavior("replace")}> - Replace Tab - </div> - {this.props.linkDoc.linksToAnnotation ? - <div className="linkEditor-followingDropdown-option" - onPointerDown={() => this.changeFollowBehavior("openExternal")}> - Always open in external page + <div className="linkEditor-followingDropdown-optionsList" style={{ display: this.openDropdown ? '' : 'none' }}> + <div className="linkEditor-followingDropdown-option" onPointerDown={() => this.changeFollowBehavior('default')}> + Default + </div> + <div className="linkEditor-followingDropdown-option" onPointerDown={() => this.changeFollowBehavior('add:left')}> + Always open in new left pane + </div> + <div className="linkEditor-followingDropdown-option" onPointerDown={() => this.changeFollowBehavior('add:right')}> + Always open in new right pane + </div> + <div className="linkEditor-followingDropdown-option" onPointerDown={() => this.changeFollowBehavior('replace:right')}> + Always replace right tab + </div> + <div className="linkEditor-followingDropdown-option" onPointerDown={() => this.changeFollowBehavior('replace:left')}> + Always replace left tab </div> - : null} + <div className="linkEditor-followingDropdown-option" onPointerDown={() => this.changeFollowBehavior('fullScreen')}> + Always open full screen + </div> + <div className="linkEditor-followingDropdown-option" onPointerDown={() => this.changeFollowBehavior('add')}> + Always open in a new tab + </div> + <div className="linkEditor-followingDropdown-option" onPointerDown={() => this.changeFollowBehavior('replace')}> + Replace Tab + </div> + {this.props.linkDoc.linksToAnnotation ? ( + <div className="linkEditor-followingDropdown-option" onPointerDown={() => this.changeFollowBehavior('openExternal')}> + Always open in external page + </div> + ) : null} + </div> </div> </div> - </div>; + ); } @action - changeInfo = () => { this.showInfo = !this.showInfo; } + changeInfo = () => { + this.showInfo = !this.showInfo; + }; render() { const destination = LinkManager.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); - return !destination ? (null) : ( + return !destination ? null : ( <div className="linkEditor" tabIndex={0} onKeyDown={e => e.stopPropagation()}> <div className="linkEditor-info"> - <Tooltip title={<><div className="dash-tooltip">Return to link menu</div></>} placement="top"> - <button className="linkEditor-button-back" - style={{ display: this.props.hideback ? "none" : "" }} - onClick={this.props.showLinks}> - <FontAwesomeIcon icon="arrow-left" size="sm" /> </button> + <Tooltip + title={ + <> + <div className="dash-tooltip">Return to link menu</div> + </> + } + placement="top"> + <button className="linkEditor-button-back" style={{ display: this.props.hideback ? 'none' : '' }} onClick={this.props.showLinks}> + <FontAwesomeIcon icon="arrow-left" size="sm" />{' '} + </button> </Tooltip> - <p className="linkEditor-linkedTo">Editing Link to: <b>{ - destination.proto?.title ?? destination.title ?? "untitled"}</b></p> - <Tooltip title={<><div className="dash-tooltip">Show more link information</div></>} placement="top"> - <div className="linkEditor-downArrow"><FontAwesomeIcon className="button" icon={this.infoIcon} size="lg" onPointerDown={this.changeInfo} /></div> + <p className="linkEditor-linkedTo"> + Editing Link to: <b>{StrCast(destination.proto?.title, StrCast(destination.title, 'untitled'))}</b> + </p> + <Tooltip + title={ + <> + <div className="dash-tooltip">Show more link information</div> + </> + } + placement="top"> + <div className="linkEditor-downArrow"> + <FontAwesomeIcon className="button" icon={this.infoIcon} size="lg" onPointerDown={this.changeInfo} /> + </div> </Tooltip> </div> - {this.showInfo ? <div className="linkEditor-moreInfo"> - <div>{this.props.linkDoc.author ? <div> <b>Author:</b> {this.props.linkDoc.author}</div> : null}</div> - <div>{this.props.linkDoc.creationDate ? <div> <b>Creation Date:</b> - {DateCast(this.props.linkDoc.creationDate).toString()}</div> : null}</div> - </div> : null} + {this.showInfo ? ( + <div className="linkEditor-moreInfo"> + <div> + {this.props.linkDoc.author ? ( + <div> + {' '} + <b>Author:</b> {StrCast(this.props.linkDoc.author)} + </div> + ) : null} + </div> + <div> + {this.props.linkDoc.creationDate ? ( + <div> + {' '} + <b>Creation Date:</b> + {DateCast(this.props.linkDoc.creationDate).toString()} + </div> + ) : null} + </div> + </div> + ) : null} {this.editDescription} {this.editRelationship} {this.editZoomFollow} {this.followingDropdown} </div> - ); } -}
\ No newline at end of file +} diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index a75e7a0c4..1e7f4f10b 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -2,7 +2,7 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@material-ui/core'; import { action, observable } from 'mobx'; -import { observer } from "mobx-react"; +import { observer } from 'mobx-react'; import { Doc, DocListCast } from '../../../fields/Doc'; import { Cast, StrCast } from '../../../fields/Types'; import { WebField } from '../../../fields/URLField'; @@ -16,8 +16,7 @@ import { undoBatch } from '../../util/UndoManager'; import { DocumentView } from '../nodes/DocumentView'; import { LinkDocPreview } from '../nodes/LinkDocPreview'; import './LinkMenuItem.scss'; -import React = require("react"); - +import React = require('react'); interface LinkMenuItemProps { groupType: string; @@ -50,22 +49,21 @@ export async function StartLinkTargetsDrag(dragEle: HTMLElement, docView: Docume }; const containingView = docView.props.ContainingCollectionView; const finishDrag = (e: DragManager.DragCompleteEvent) => - e.docDragData && (e.docDragData.droppedDocuments = - dragData.draggedDocuments.reduce((droppedDocs, d) => { - const dvs = DocumentManager.Instance.getDocumentViews(d).filter(dv => dv.props.ContainingCollectionView === containingView); - if (dvs.length) { - dvs.forEach(dv => droppedDocs.push(dv.props.Document)); - } else { - droppedDocs.push(Doc.MakeAlias(d)); - } - return droppedDocs; - }, [] as Doc[])); + e.docDragData && + (e.docDragData.droppedDocuments = dragData.draggedDocuments.reduce((droppedDocs, d) => { + const dvs = DocumentManager.Instance.getDocumentViews(d).filter(dv => dv.props.ContainingCollectionView === containingView); + if (dvs.length) { + dvs.forEach(dv => droppedDocs.push(dv.props.Document)); + } else { + droppedDocs.push(Doc.MakeAlias(d)); + } + return droppedDocs; + }, [] as Doc[])); DragManager.StartDrag([dragEle], dragData, downX, downY, undefined, finishDrag); } } - @observer export class LinkMenuItem extends React.Component<LinkMenuItemProps> { private _drag = React.createRef<HTMLDivElement>(); @@ -74,20 +72,31 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { _buttonRef = React.createRef<HTMLDivElement>(); @observable private _showMore: boolean = false; - @action toggleShowMore(e: React.PointerEvent) { e.stopPropagation(); this._showMore = !this._showMore; } + @action toggleShowMore(e: React.PointerEvent) { + e.stopPropagation(); + this._showMore = !this._showMore; + } onEdit = (e: React.PointerEvent): void => { LinkManager.currentLink = this.props.linkDoc; - setupMoveUpEvents(this, e, e => { - const dragData = new DragManager.DocumentDragData([this.props.linkDoc], "alias"); - dragData.removeDropProperties = ["hidden"]; - DragManager.StartDocumentDrag([this._editRef.current!], dragData, e.x, e.y); - return true; - }, emptyFunction, () => this.props.showEditor(this.props.linkDoc)); - } + setupMoveUpEvents( + this, + e, + e => { + const dragData = new DragManager.DocumentDragData([this.props.linkDoc], 'alias'); + dragData.removeDropProperties = ['hidden']; + DragManager.StartDocumentDrag([this._editRef.current!], dragData, e.x, e.y); + return true; + }, + emptyFunction, + () => this.props.showEditor(this.props.linkDoc) + ); + }; onLinkButtonDown = (e: React.PointerEvent): void => { - setupMoveUpEvents(this, e, + setupMoveUpEvents( + this, + e, e => { const eleClone: any = this._drag.current!.cloneNode(true); eleClone.style.transform = `translate(${e.x}px, ${e.y}px)`; @@ -99,109 +108,170 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { () => { this.props.clearLinkEditor(); if (this.props.itemHandler) { - this.props.itemHandler?.(this.props.linkDoc); } else { - const focusDoc = Cast(this.props.linkDoc.anchor1, Doc, null)?.annotationOn === this.props.sourceDoc ? Cast(this.props.linkDoc.anchor1, Doc, null) : - Cast(this.props.linkDoc.anchor2, Doc, null)?.annotationOn === this.props.sourceDoc ? Cast(this.props.linkDoc.anchor12, Doc, null) : undefined; + const focusDoc = + Cast(this.props.linkDoc.anchor1, Doc, null)?.annotationOn === this.props.sourceDoc + ? Cast(this.props.linkDoc.anchor1, Doc, null) + : Cast(this.props.linkDoc.anchor2, Doc, null)?.annotationOn === this.props.sourceDoc + ? Cast(this.props.linkDoc.anchor12, Doc, null) + : undefined; if (focusDoc) this.props.docView.ComponentView?.scrollFocus?.(focusDoc, true); LinkManager.FollowLink(this.props.linkDoc, this.props.sourceDoc, this.props.docView.props, false); } - }); - } + } + ); + }; deleteLink = (e: React.PointerEvent): void => { - setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => { - this.props.linkDoc.linksToAnnotation && Hypothesis.deleteLink(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc); - LinkManager.Instance.deleteLink(this.props.linkDoc); - }))); - } + setupMoveUpEvents( + this, + e, + returnFalse, + emptyFunction, + undoBatch( + action(() => { + this.props.linkDoc.linksToAnnotation && Hypothesis.deleteLink(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc); + LinkManager.Instance.deleteLink(this.props.linkDoc); + }) + ) + ); + }; autoMove = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => this.props.linkDoc.linkAutoMove = !this.props.linkDoc.linkAutoMove))); - } + setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => (this.props.linkDoc.linkAutoMove = !this.props.linkDoc.linkAutoMove)))); + }; showLink = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => this.props.linkDoc.linkDisplay = !this.props.linkDoc.linkDisplay))); - } + setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => (this.props.linkDoc.linkDisplay = !this.props.linkDoc.linkDisplay)))); + }; showAnchor = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => this.props.linkDoc.hidden = !this.props.linkDoc.hidden))); - } + setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => (this.props.linkDoc.hidden = !this.props.linkDoc.hidden)))); + }; render() { const destinationIcon = Doc.toIcon(this.props.destinationDoc) as any as IconProp; - const title = StrCast(this.props.destinationDoc.title).length > 18 ? - StrCast(this.props.destinationDoc.title).substr(0, 14) + "..." : this.props.destinationDoc.title; + const title = StrCast(this.props.destinationDoc.title).length > 18 ? StrCast(this.props.destinationDoc.title).substr(0, 14) + '...' : this.props.destinationDoc.title; // ... // from anika to bob: here's where the text that is specifically linked would show up (linkDoc.storedText) // ... - const source = this.props.sourceDoc.type === DocumentType.RTF ? this.props.linkDoc.storedText ? - StrCast(this.props.linkDoc.storedText).length > 17 ? - StrCast(this.props.linkDoc.storedText).substr(0, 18) - : this.props.linkDoc.storedText : undefined : undefined; + const source = + this.props.sourceDoc.type === DocumentType.RTF + ? this.props.linkDoc.storedText + ? StrCast(this.props.linkDoc.storedText).length > 17 + ? StrCast(this.props.linkDoc.storedText).substr(0, 18) + : this.props.linkDoc.storedText + : undefined + : undefined; return ( <div className="linkMenu-item"> - <div className={"linkMenu-item-content expand-two"}> - - <div ref={this._drag} className="linkMenu-name" //title="drag to view target. click to customize." + <div className={'linkMenu-item-content expand-two'}> + <div + ref={this._drag} + className="linkMenu-name" //title="drag to view target. click to customize." onPointerLeave={LinkDocPreview.Clear} - onPointerEnter={e => this.props.linkDoc && LinkDocPreview.SetLinkInfo({ - docProps: this.props.docView.props, - linkSrc: this.props.sourceDoc, - linkDoc: this.props.linkDoc, - showHeader: false, - location: [e.clientX, e.clientY + 20] - })} + onPointerEnter={e => + this.props.linkDoc && + LinkDocPreview.SetLinkInfo({ + docProps: this.props.docView.props, + linkSrc: this.props.sourceDoc, + linkDoc: this.props.linkDoc, + showHeader: false, + location: [e.clientX, e.clientY + 20], + }) + } onPointerDown={this.onLinkButtonDown}> - <div className="linkMenu-text"> - {source ? <p className="linkMenu-source-title"> <b>Source: {source}</b></p> : null} + {source ? ( + <p className="linkMenu-source-title"> + {' '} + <b>Source: {StrCast(source)}</b> + </p> + ) : null} <div className="linkMenu-title-wrapper"> - <div className="destination-icon-wrapper" > + <div className="destination-icon-wrapper"> <FontAwesomeIcon className="destination-icon" icon={destinationIcon} size="sm" /> </div> <p className="linkMenu-destination-title"> - {this.props.linkDoc.linksToAnnotation && Cast(this.props.destinationDoc.data, WebField)?.url.href === this.props.linkDoc.annotationUri ? "Annotation in" : ""} {title} + {this.props.linkDoc.linksToAnnotation && Cast(this.props.destinationDoc.data, WebField)?.url.href === this.props.linkDoc.annotationUri ? 'Annotation in' : ''} {StrCast(title)} </p> </div> - {!this.props.linkDoc.description ? (null) : <p className="linkMenu-description">{StrCast(this.props.linkDoc.description)}</p>} + {!this.props.linkDoc.description ? null : <p className="linkMenu-description">{StrCast(this.props.linkDoc.description)}</p>} </div> - <div className="linkMenu-item-buttons" ref={this._buttonRef} > - - <Tooltip title={<><div className="dash-tooltip">{this.props.linkDoc.hidden ? "Show Link Anchor" : "Hide Link Anchor"}</div></>}> - <div className="button" ref={this._editRef} style={{ background: this.props.linkDoc.hidden ? "" : "#4476f7" /* $medium-blue */ }} onPointerDown={this.showAnchor} onClick={e => e.stopPropagation()}> - <FontAwesomeIcon className="fa-icon" icon={"eye"} size="sm" /></div> + <div className="linkMenu-item-buttons" ref={this._buttonRef}> + <Tooltip + title={ + <> + <div className="dash-tooltip">{this.props.linkDoc.hidden ? 'Show Link Anchor' : 'Hide Link Anchor'}</div> + </> + }> + <div className="button" ref={this._editRef} style={{ background: this.props.linkDoc.hidden ? '' : '#4476f7' /* $medium-blue */ }} onPointerDown={this.showAnchor} onClick={e => e.stopPropagation()}> + <FontAwesomeIcon className="fa-icon" icon={'eye'} size="sm" /> + </div> </Tooltip> - <Tooltip title={<><div className="dash-tooltip">{this.props.linkDoc.linkDisplay ? "Hide Link Line" : "Show Link Line"}</div></>}> - <div className="button" ref={this._editRef} style={{ background: this.props.linkDoc.hidden ? "gray" : this.props.linkDoc.linkDisplay ? "#4476f7"/* $medium-blue */ : "" }} onPointerDown={this.showLink} onClick={e => e.stopPropagation()}> - <FontAwesomeIcon className="fa-icon" icon={"project-diagram"} size="sm" /></div> + <Tooltip + title={ + <> + <div className="dash-tooltip">{this.props.linkDoc.linkDisplay ? 'Hide Link Line' : 'Show Link Line'}</div> + </> + }> + <div + className="button" + ref={this._editRef} + style={{ background: this.props.linkDoc.hidden ? 'gray' : this.props.linkDoc.linkDisplay ? '#4476f7' /* $medium-blue */ : '' }} + onPointerDown={this.showLink} + onClick={e => e.stopPropagation()}> + <FontAwesomeIcon className="fa-icon" icon={'project-diagram'} size="sm" /> + </div> </Tooltip> - <Tooltip title={<><div className="dash-tooltip">{this.props.linkDoc.linkAutoMove ? "Click to freeze link anchor position" : "Click to auto move link anchor"}</div></>}> - <div className="button" ref={this._editRef} style={{ background: this.props.linkDoc.hidden ? "gray" : !this.props.linkDoc.linkAutoMove ? "" : "#4476f7" /* $medium-blue */ }} onPointerDown={this.autoMove} onClick={e => e.stopPropagation()}> - <FontAwesomeIcon className="fa-icon" icon={"play"} size="sm" /></div> + <Tooltip + title={ + <> + <div className="dash-tooltip">{this.props.linkDoc.linkAutoMove ? 'Click to freeze link anchor position' : 'Click to auto move link anchor'}</div> + </> + }> + <div + className="button" + ref={this._editRef} + style={{ background: this.props.linkDoc.hidden ? 'gray' : !this.props.linkDoc.linkAutoMove ? '' : '#4476f7' /* $medium-blue */ }} + onPointerDown={this.autoMove} + onClick={e => e.stopPropagation()}> + <FontAwesomeIcon className="fa-icon" icon={'play'} size="sm" /> + </div> </Tooltip> - <Tooltip title={<><div className="dash-tooltip">Edit Link</div></>}> + <Tooltip + title={ + <> + <div className="dash-tooltip">Edit Link</div> + </> + }> <div className="button" ref={this._editRef} onPointerDown={this.onEdit} onClick={e => e.stopPropagation()}> - <FontAwesomeIcon className="fa-icon" icon="edit" size="sm" /></div> + <FontAwesomeIcon className="fa-icon" icon="edit" size="sm" /> + </div> </Tooltip> - <Tooltip title={<><div className="dash-tooltip">Delete Link</div></>}> + <Tooltip + title={ + <> + <div className="dash-tooltip">Delete Link</div> + </> + }> <div className="button" onPointerDown={this.deleteLink} onClick={e => e.stopPropagation()}> - <FontAwesomeIcon className="fa-icon" icon="trash" size="sm" /></div> + <FontAwesomeIcon className="fa-icon" icon="trash" size="sm" /> + </div> </Tooltip> </div> </div> </div> - - </div > + </div> ); } -}
\ No newline at end of file +} |
