diff options
Diffstat (limited to 'src/client/views/linking')
| -rw-r--r-- | src/client/views/linking/LinkEditor.scss | 65 | ||||
| -rw-r--r-- | src/client/views/linking/LinkEditor.tsx | 173 | ||||
| -rw-r--r-- | src/client/views/linking/LinkMenuItem.tsx | 93 |
3 files changed, 141 insertions, 190 deletions
diff --git a/src/client/views/linking/LinkEditor.scss b/src/client/views/linking/LinkEditor.scss index 1d6496d3c..b0ee4e46d 100644 --- a/src/client/views/linking/LinkEditor.scss +++ b/src/client/views/linking/LinkEditor.scss @@ -1,10 +1,11 @@ -@import "../global/globalCssVariables"; +@import '../global/globalCssVariables'; .linkEditor { width: 100%; height: auto; font-size: 13px; // TODO user-select: none; + max-width: 280px; } .linkEditor-button-back { @@ -20,19 +21,20 @@ } .linkEditor-info { - //border-bottom: 0.5px solid $light-gray; - //padding-bottom: 1px; - padding: 12px; + padding-top: 12px; padding-left: 5px; + padding-bottom: 3px; //margin-bottom: 6px; display: flex; justify-content: space-between; color: black; .linkEditor-linkedTo { - width: calc(100% - 26px); - padding-left: 5px; - padding-right: 5px; + width: calc(100% - 46px); + overflow: hidden; + position: relative; + text-overflow: ellipsis; + white-space: pre; .linkEditor-downArrow { &:hover { @@ -77,11 +79,14 @@ width: 20px; } } +.linkEditor-deleteBtn { + padding-left: 3px; +} .linkEditor-description { padding-left: 26px; - padding-right: 6.5px; padding-bottom: 3.5px; + display: flex; .linkEditor-description-label { text-decoration-color: black; @@ -96,7 +101,6 @@ //border: 1px solid grey; //border-radius: 4px; padding-left: 2px; - padding-right: 2px; //margin-right: 4px; color: black; text-decoration-color: grey; @@ -104,17 +108,13 @@ .linkEditor-description-add-button { display: inline; - /* float: right; */ border-radius: 7px; font-size: 9px; background: black; - /* padding: 3px; */ - padding-top: 4px; - padding-left: 7px; - padding-bottom: 4px; - padding-right: 8px; height: 80%; color: white; + padding: 3px; + margin-left: 3px; &:hover { cursor: pointer; @@ -146,6 +146,7 @@ padding-left: 26px; padding-right: 6.5px; padding-bottom: 15px; + display: flex; &:hover { cursor: pointer; @@ -153,12 +154,11 @@ .linkEditor-followingDropdown-label { color: black; + padding-right: 3px; } .linkEditor-followingDropdown-dropdown { - .linkEditor-followingDropdown-header { - border: 1px solid grey; border-radius: 4px; //background-color: rgb(236, 236, 236); @@ -195,27 +195,25 @@ background-color: rgb(187, 220, 231); } } - } } - - } - - - - - .linkEditor-button, .linkEditor-addbutton { - width: 18px; - height: 18px; - padding: 0; - // font-size: 12px; - border-radius: 10px; - - + width: 15%; + border-radius: 7px; + font-size: 9px; + background: black; + padding: 3px; + height: 80%; + color: white; + text-align: center; + margin: auto; + margin-left: 3px; + > svg { + margin: auto; + } &:disabled { background-color: gray; } @@ -270,7 +268,6 @@ } } - .linkEditor-dropdown { width: 100%; position: relative; @@ -334,4 +331,4 @@ .linkEditor-button { margin-left: 3px; } -}
\ No newline at end of file +} diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx index ba301962b..1697062f4 100644 --- a/src/client/views/linking/LinkEditor.tsx +++ b/src/client/views/linking/LinkEditor.tsx @@ -3,32 +3,27 @@ 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 { DateCast, StrCast, Cast, BoolCast } 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 { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../Utils'; interface LinkEditorProps { sourceDoc: Doc; linkDoc: Doc; - showLinks: () => void; + showLinks?: () => void; hideback?: boolean; } @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 zoomFollow = BoolCast(this.props.sourceDoc.followLinkZoom); + @observable audioFollow = BoolCast(this.props.sourceDoc.followLinkAudio); @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'; @@ -37,12 +32,6 @@ export class LinkEditor extends React.Component<LinkEditorProps> { //@observable description = this.props.linkDoc.description ? StrCast(this.props.linkDoc.description) : "DESCRIPTION"; @undoBatch - deleteLink = (): void => { - LinkManager.Instance.deleteLink(this.props.linkDoc); - this.props.showLinks(); - }; - - @undoBatch setRelationshipValue = action((value: string) => { if (LinkManager.currentLink) { const prevRelationship = LinkManager.currentLink.linkRelationship as string; @@ -159,8 +148,12 @@ export class LinkEditor extends React.Component<LinkEditorProps> { this.relationship = e.target.value; }; @action - handleZoomFollowChange = (e: React.ChangeEvent<HTMLInputElement>) => { - this.props.sourceDoc.followLinkZoom = e.target.checked; + handleZoomFollowChange = () => { + this.props.sourceDoc.followLinkZoom = !this.props.sourceDoc.followLinkZoom; + }; + @action + handleAudioFollowChange = () => { + this.props.sourceDoc.followLinkAudio = !this.props.sourceDoc.followLinkAudio; }; @action handleRelationshipSearchChange = (result: string) => { @@ -173,7 +166,7 @@ export class LinkEditor extends React.Component<LinkEditorProps> { //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-label">Relationship:</div> <div className="linkEditor-description-input"> <div className="linkEditor-description-editing"> <input @@ -203,7 +196,23 @@ export class LinkEditor extends React.Component<LinkEditorProps> { <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} /> + <input type="checkbox" onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, this.handleZoomFollowChange)} defaultChecked={this.zoomFollow} /> + </div> + </div> + </div> + ); + } + + @computed + get editAudioFollow() { + //NOTE: confusingly, the classnames for the following relationship JSX elements are the same as the for the description elements for shared CSS + console.log('AudioFollow:' + this.audioFollow); + return ( + <div className="linkEditor-zoomFollow"> + <div className="linkEditor-zoomFollow-label">Play Target Audio:</div> + <div className="linkEditor-zoomFollow-input"> + <div className="linkEditor-zoomFollow-editing"> + <input type="checkbox" onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, this.handleAudioFollowChange)} defaultChecked={this.audioFollow} /> </div> </div> </div> @@ -214,7 +223,7 @@ export class LinkEditor extends React.Component<LinkEditorProps> { get editDescription() { return ( <div className="linkEditor-description"> - <div className="linkEditor-description-label">Link Description:</div> + <div className="linkEditor-description-label">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> @@ -284,68 +293,100 @@ export class LinkEditor extends React.Component<LinkEditorProps> { ); } - @action - changeInfo = () => { - this.showInfo = !this.showInfo; + autoMove = (e: React.PointerEvent) => { + setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => (this.props.linkDoc.linkAutoMove = !this.props.linkDoc.linkAutoMove)))); + }; + + showAnchor = (e: React.PointerEvent) => { + setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => (this.props.linkDoc.hidden = !this.props.linkDoc.hidden)))); + }; + + showLink = (e: React.PointerEvent) => { + setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => (this.props.linkDoc.linkDisplay = !this.props.linkDoc.linkDisplay)))); + }; + + deleteLink = (e: React.PointerEvent): void => { + setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => LinkManager.Instance.deleteLink(this.props.linkDoc)))); }; render() { const destination = LinkManager.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); return !destination ? null : ( - <div className="linkEditor" tabIndex={0} onKeyDown={e => e.stopPropagation()}> + <div className="linkEditor" tabIndex={0} onKeyDown={e => e.stopPropagation()} onPointerDown={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> + {!this.props.showLinks ? null : ( + <Tooltip title={<div className="dash-tooltip">Return to link menu</div>} placement="top"> + <button className="linkEditor-button-back" style={{ display: this.props.hideback ? 'none' : '' }} onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => this.props.showLinks?.())}> + <FontAwesomeIcon icon="arrow-left" size="sm" />{' '} + </button> + </Tooltip> + )} <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} /> + <Tooltip title={<div className="dash-tooltip">Delete Link</div>}> + <div className="linkEditor-deleteBtn" onPointerDown={this.deleteLink} onClick={e => e.stopPropagation()}> + <FontAwesomeIcon className="fa-icon" icon="trash" size="sm" /> </div> </Tooltip> </div> - {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} + <div className="linkEditor-moreInfo"> + {this.props.linkDoc.author ? ( + <> + {' '} + <b>Author:</b> {StrCast(this.props.linkDoc.author)} + </> + ) : null} + {this.props.linkDoc.creationDate ? ( + <> + {' '} + <b>Creation Date:</b> + {DateCast(this.props.linkDoc.creationDate).toString()} + </> + ) : null} + </div> {this.editDescription} {this.editRelationship} {this.editZoomFollow} + {this.editAudioFollow} + <div className="linkEditor-description"> + Show Anchor: + <Tooltip title={<div className="dash-tooltip">{this.props.linkDoc.hidden ? 'Show Link Anchor' : 'Hide Link Anchor'}</div>}> + <div + className="linkEditor-button" + style={{ background: this.props.linkDoc.hidden ? 'gray' : '#4476f7' /* $medium-blue */ }} + onPointerDown={this.showAnchor} + onClick={e => e.stopPropagation()}> + <FontAwesomeIcon className="fa-icon" icon={'eye'} size="sm" /> + </div> + </Tooltip> + </div> + <div className="linkEditor-description"> + Show Link Line: + <Tooltip title={<div className="dash-tooltip">{this.props.linkDoc.linkDisplay ? 'Hide Link Line' : 'Show Link Line'}</div>}> + <div + className="linkEditor-button" + 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> + </div> + <div className="linkEditor-description"> + Freeze Anchor: + <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="linkEditor-button" + 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> + </div> {this.followingDropdown} </div> ); diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index ed856a4ab..3f9db2612 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -6,14 +6,12 @@ import { observer } from 'mobx-react'; import { Doc, DocListCast } from '../../../fields/Doc'; import { Cast, StrCast } from '../../../fields/Types'; import { WebField } from '../../../fields/URLField'; -import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../Utils'; +import { emptyFunction, setupMoveUpEvents } from '../../../Utils'; import { DocumentType } from '../../documents/DocumentTypes'; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager } from '../../util/DragManager'; -import { Hypothesis } from '../../util/HypothesisUtils'; import { LinkFollower } from '../../util/LinkFollower'; import { LinkManager } from '../../util/LinkManager'; -import { undoBatch } from '../../util/UndoManager'; import { DocumentView } from '../nodes/DocumentView'; import { LinkDocPreview } from '../nodes/LinkDocPreview'; import './LinkMenuItem.scss'; @@ -125,33 +123,6 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { ); }; - 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); - }) - ) - ); - }; - - autoMove = (e: React.PointerEvent) => { - 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)))); - }; - - showAnchor = (e: React.PointerEvent) => { - 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; @@ -183,7 +154,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { linkSrc: this.props.sourceDoc, linkDoc: this.props.linkDoc, showHeader: false, - location: [e.clientX, e.clientY + 20], + location: [this._drag.current?.getBoundingClientRect().right ?? 100, this._drag.current?.getBoundingClientRect().top ?? e.clientY], }) } onPointerDown={this.onLinkButtonDown}> @@ -206,69 +177,11 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { </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> - - <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> </Tooltip> - <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> - </Tooltip> </div> </div> </div> |
