aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/DocumentLinksButton.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/DocumentLinksButton.tsx')
-rw-r--r--src/client/views/nodes/DocumentLinksButton.tsx107
1 files changed, 62 insertions, 45 deletions
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 50a7f5d7b..165057d21 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -1,22 +1,22 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Tooltip } from '@material-ui/core';
-import { action, computed, observable, runInAction } from 'mobx';
+import { Tooltip } from '@mui/material';
+import { action, computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
+import * as React from 'react';
+import { StopEvent, emptyFunction, returnFalse, setupMoveUpEvents } from '../../../Utils';
import { Doc } from '../../../fields/Doc';
import { StrCast } from '../../../fields/Types';
-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 { UndoManager, undoBatch } from '../../util/UndoManager';
+import { ObservableReactComponent } from '../ObservableReactComponent';
import './DocumentLinksButton.scss';
import { DocumentView } from './DocumentView';
import { LinkDescriptionPopup } from './LinkDescriptionPopup';
import { TaskCompletionBox } from './TaskCompletedBox';
import { PinProps } from './trails';
-import React = require('react');
-import _ = require('lodash');
interface DocumentLinksButtonProps {
View: DocumentView;
@@ -29,25 +29,43 @@ interface DocumentLinksButtonProps {
scaling?: () => number; // how uch doc is scaled so that link buttons can invert it
hideCount?: () => boolean;
}
+
+export class DocButtonState {
+ @observable public StartLink: Doc | undefined = undefined; //origin's Doc, if defined
+ @observable public StartLinkView: DocumentView | undefined = undefined;
+ @observable public AnnotationId: string | undefined = undefined;
+ @observable public AnnotationUri: string | undefined = undefined;
+ @observable public LinkEditorDocView: DocumentView | undefined = undefined;
+ public static _instance: DocButtonState | undefined;
+ public static get Instance() {
+ return DocButtonState._instance ?? (DocButtonState._instance = new DocButtonState());
+ }
+ constructor() {
+ makeObservable(this);
+ }
+}
@observer
-export class DocumentLinksButton extends React.Component<DocumentLinksButtonProps, {}> {
+export class DocumentLinksButton extends ObservableReactComponent<DocumentLinksButtonProps> {
private _linkButton = React.createRef<HTMLDivElement>();
- @observable public static StartLink: Doc | undefined; //origin's Doc, if defined
- @observable public static StartLinkView: DocumentView | undefined;
- @observable public static AnnotationId: string | undefined;
- @observable public static AnnotationUri: string | undefined;
- @observable public static LinkEditorDocView: DocumentView | undefined;
+ public static get StartLink() { return DocButtonState.Instance.StartLink; } // prettier-ignore
+ public static set StartLink(value) { runInAction(() => (DocButtonState.Instance.StartLink = value)); } // prettier-ignore
+ @observable public static StartLinkView: DocumentView | undefined = undefined;
+ @observable public static AnnotationId: string | undefined = undefined;
+ @observable public static AnnotationUri: string | undefined = undefined;
+ constructor(props: any) {
+ super(props);
+ makeObservable(this);
+ }
- @action
@undoBatch
onLinkButtonMoved = (e: PointerEvent) => {
- if (this.props.InMenu && this.props.StartLink) {
+ if (this._props.InMenu && this._props.StartLink) {
if (this._linkButton.current !== null) {
const linkDrag = UndoManager.StartBatch('Drag Link');
- this.props.View &&
- DragManager.StartLinkDrag(this._linkButton.current, this.props.View, this.props.View.ComponentView?.getAnchor, e.pageX, e.pageY, {
+ this._props.View &&
+ DragManager.StartLinkDrag(this._linkButton.current, this._props.View, this._props.View.ComponentView?.getAnchor, e.pageX, e.pageY, {
dragComplete: dropEv => {
- if (this.props.View && dropEv.linkDocument) {
+ if (this._props.View && dropEv.linkDocument) {
// dropEv.linkDocument equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop
!dropEv.linkDocument.link_relationship && (Doc.GetProto(dropEv.linkDocument).link_relationship = 'hyperlink');
}
@@ -69,11 +87,11 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
this.onLinkButtonMoved,
emptyFunction,
action((e, doubleTap) => {
- doubleTap && DocumentView.showBackLinks(this.props.View.rootDoc);
+ doubleTap && DocumentView.showBackLinks(this._props.View.Document);
}),
undefined,
undefined,
- action(() => (DocumentLinksButton.LinkEditorDocView = this.props.View))
+ action(() => (DocButtonState.Instance.LinkEditorDocView = this._props.View))
);
};
@@ -84,33 +102,32 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
this.onLinkButtonMoved,
emptyFunction,
action((e, doubleTap) => {
- if (doubleTap && this.props.InMenu && this.props.StartLink) {
- //action(() => Doc.BrushDoc(this.props.View.Document));
- if (DocumentLinksButton.StartLink === this.props.View.props.Document) {
+ if (doubleTap && this._props.InMenu && this._props.StartLink) {
+ //action(() => Doc.BrushDoc(this._props.View.Document));
+ if (DocumentLinksButton.StartLink === this._props.View.Document) {
DocumentLinksButton.StartLink = undefined;
DocumentLinksButton.StartLinkView = undefined;
} else {
- DocumentLinksButton.StartLink = this.props.View.props.Document;
- DocumentLinksButton.StartLinkView = this.props.View;
+ DocumentLinksButton.StartLink = this._props.View.Document;
+ DocumentLinksButton.StartLinkView = this._props.View;
}
}
})
);
};
- @action
@undoBatch
onLinkClick = (e: React.MouseEvent): void => {
- if (this.props.InMenu && this.props.StartLink) {
+ if (this._props.InMenu && this._props.StartLink) {
DocumentLinksButton.AnnotationId = undefined;
DocumentLinksButton.AnnotationUri = undefined;
- if (DocumentLinksButton.StartLink === this.props.View.props.Document) {
+ if (DocumentLinksButton.StartLink === this._props.View.Document) {
DocumentLinksButton.StartLink = undefined;
DocumentLinksButton.StartLinkView = undefined;
} else {
//if this LinkButton's Document is undefined
- DocumentLinksButton.StartLink = this.props.View.props.Document;
- DocumentLinksButton.StartLinkView = this.props.View;
+ DocumentLinksButton.StartLink = this._props.View.Document;
+ DocumentLinksButton.StartLinkView = this._props.View;
}
}
};
@@ -121,7 +138,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
e,
returnFalse,
emptyFunction,
- action(e => DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this.props.View.props.Document, true, this.props.View))
+ action(e => DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this._props.View.Document, true, this._props.View))
);
};
@@ -133,7 +150,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
DocumentLinksButton.StartLinkView = undefined;
DocumentLinksButton.AnnotationId = undefined;
DocumentLinksButton.AnnotationUri = undefined;
- //!this.props.StartLink
+ //!this._props.StartLink
} else if (startLink !== endLink) {
endLink = endLinkView?.docView?._componentView?.getAnchor?.(true, pinProps) || endLink;
startLink = DocumentLinksButton.StartLinkView?.docView?._componentView?.getAnchor?.(true) || startLink;
@@ -190,8 +207,8 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
@computed get filteredLinks() {
const results = [] as Doc[];
- const filters = this.props.View.props.childFilters();
- Array.from(new Set<Doc>(this.props.View.allLinks)).forEach(link => {
+ const filters = this._props.View._props.childFilters();
+ Array.from(new Set<Doc>(this._props.View.allLinks)).forEach(link => {
if (DocUtils.FilterDocs([link], filters, []).length || DocUtils.FilterDocs([link.link_anchor_2 as Doc], filters, []).length || DocUtils.FilterDocs([link.link_anchor_1 as Doc], filters, []).length) {
results.push(link);
}
@@ -206,8 +223,8 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
*/
@computed get linkButtonInner() {
const btnDim = 30;
- const isActive = DocumentLinksButton.StartLink === this.props.View.props.Document && this.props.StartLink;
- const scaling = Math.min(1, this.props.scaling?.() || 1);
+ const isActive = DocumentLinksButton.StartLink === this._props.View.Document && this._props.StartLink;
+ const scaling = Math.min(1, this._props.scaling?.() || 1);
const showLinkCount = (onHover?: boolean, offset?: boolean) => (
<div
className="documentLinksButton-showCount"
@@ -221,16 +238,16 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
<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)
+ return this._props.ShowCount ? (
+ showLinkCount(this._props.OnHover, this._props.Bottom)
) : (
<div className="documentLinksButton-menu">
- {this.props.StartLink ? ( //if link has been started from current node, then set behavior of link button to deactivate linking when clicked again
+ {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.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document ? ( //if the origin node is not this node
+ {!this._props.StartLink && DocumentLinksButton.StartLink !== this._props.View.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>
@@ -240,21 +257,21 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
}
render() {
- if (this.props.hideCount?.()) return null;
- const menuTitle = this.props.StartLink ? 'Drag or tap to start link' : 'Tap to complete link';
+ if (this._props.hideCount?.()) return null;
+ 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.ShowCount ? buttonTitle : menuTitle;
+ 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 : (
+ return !Array.from(this.filteredLinks).length && !this._props.AlwaysOn ? null : (
<div
className="documentLinksButton-wrapper"
style={{
- position: this.props.InMenu ? 'relative' : 'absolute',
+ position: this._props.InMenu ? 'relative' : 'absolute',
top: 0,
pointerEvents: 'none',
}}>
- {DocumentLinksButton.LinkEditorDocView ? this.linkButtonInner : <Tooltip title={<div className="dash-tooltip">{title}</div>}>{this.linkButtonInner}</Tooltip>}
+ {DocButtonState.Instance.LinkEditorDocView ? this.linkButtonInner : <Tooltip title={<div className="dash-tooltip">{title}</div>}>{this.linkButtonInner}</Tooltip>}
</div>
);
}