aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/linking
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/linking')
-rw-r--r--src/client/views/linking/LinkEditor.scss23
-rw-r--r--src/client/views/linking/LinkEditor.tsx163
-rw-r--r--src/client/views/linking/LinkFollowBox.scss93
-rw-r--r--src/client/views/linking/LinkFollowBox.tsx571
-rw-r--r--src/client/views/linking/LinkMenu.tsx4
-rw-r--r--src/client/views/linking/LinkMenuGroup.tsx4
-rw-r--r--src/client/views/linking/LinkMenuItem.tsx58
7 files changed, 74 insertions, 842 deletions
diff --git a/src/client/views/linking/LinkEditor.scss b/src/client/views/linking/LinkEditor.scss
index fc5f2410c..b47c8976e 100644
--- a/src/client/views/linking/LinkEditor.scss
+++ b/src/client/views/linking/LinkEditor.scss
@@ -4,6 +4,7 @@
width: 100%;
height: auto;
font-size: 12px; // TODO
+ user-select: none;
}
.linkEditor-back {
@@ -22,10 +23,9 @@
}
}
-.linkEditor-button {
- width: 20px;
- height: 20px;
- margin-left: 6px;
+.linkEditor-button, .linkEditor-addbutton {
+ width: 18px;
+ height: 18px;
padding: 0;
// font-size: 12px;
border-radius: 10px;
@@ -34,6 +34,9 @@
background-color: gray;
}
}
+.linkEditor-addbutton{
+ margin-left: 0px;
+}
.linkEditor-groupsLabel {
display: flex;
@@ -49,10 +52,11 @@
.linkEditor-group-row {
display: flex;
margin-bottom: 3px;
+ }
- .linkEditor-group-row-label {
- margin-right: 6px;
- }
+ .linkEditor-group-row-label {
+ margin-right: 6px;
+ display:inline-block;
}
.linkEditor-metadata-row {
@@ -118,7 +122,6 @@
.linkEditor-typeButton {
background-color: transparent;
color: $dark-color;
- width: 100%;
height: 20px;
padding: 0 3px;
padding-bottom: 2px;
@@ -127,6 +130,8 @@
letter-spacing: normal;
font-size: 12px;
font-weight: bold;
+ display: inline-block;
+ width: calc(100% - 40px);
&:hover {
background-color: $light-color;
@@ -140,6 +145,6 @@
margin-top: 5px;
.linkEditor-button {
- margin-left: 6px;
+ 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 e3bf6b5f8..ac4f8a3cf 100644
--- a/src/client/views/linking/LinkEditor.tsx
+++ b/src/client/views/linking/LinkEditor.tsx
@@ -1,17 +1,14 @@
-import { observable, computed, action, trace } from "mobx";
-import React = require("react");
+import { library } from "@fortawesome/fontawesome-svg-core";
+import { faArrowLeft, faCog, faEllipsisV, faExchangeAlt, faPlus, faTable, faTimes, faTrash } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { action, observable } from "mobx";
import { observer } from "mobx-react";
-import './LinkEditor.scss';
-import { StrCast, Cast, FieldValue } from "../../../new_fields/Types";
import { Doc } from "../../../new_fields/Doc";
-import { LinkManager } from "../../util/LinkManager";
-import { Docs } from "../../documents/Documents";
+import { StrCast } from "../../../new_fields/Types";
import { Utils } from "../../../Utils";
-import { faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, faTimes, faPlus } from '@fortawesome/free-solid-svg-icons';
-import { library } from "@fortawesome/fontawesome-svg-core";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { SetupDrag } from "../../util/DragManager";
-import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeaderField";
+import { LinkManager } from "../../util/LinkManager";
+import './LinkEditor.scss';
+import React = require("react");
library.add(faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, faTimes, faPlus);
@@ -108,7 +105,7 @@ class GroupTypesDropdown extends React.Component<GroupTypesDropdownProps> {
if (this._isEditing || this._groupType === "") {
return (
<div className="linkEditor-dropdown">
- <input type="text" value={this._groupType} placeholder="Search for or create a new group"
+ <input type="text" value={this._groupType === "-ungrouped-" ? "" : this._groupType} placeholder="Search for or create a new group"
onChange={e => this.onChange(e.target.value)} onKeyDown={this.onKeyDown} autoFocus></input>
<div className="linkEditor-options-wrapper">
{this.renderOptions()}
@@ -166,7 +163,7 @@ class LinkMetadataEditor extends React.Component<LinkMetadataEditorProps> {
setMetadataValue = (value: string): void => {
if (!this._keyError) {
this._value = value;
- this.props.mdDoc[this._key] = value;
+ Doc.GetProto(this.props.mdDoc)[this._key] = value;
}
}
@@ -187,7 +184,7 @@ class LinkMetadataEditor extends React.Component<LinkMetadataEditorProps> {
<div className="linkEditor-metadata-row">
<input className={this._keyError ? "linkEditor-error" : ""} type="text" value={this._key === "new key" ? "" : this._key} placeholder="key" onChange={e => this.setMetadataKey(e.target.value)}></input>:
<input type="text" value={this._value} placeholder="value" onChange={e => this.setMetadataValue(e.target.value)}></input>
- <button onClick={() => this.removeMetadata()}><FontAwesomeIcon icon="times" size="sm" /></button>
+ <button title="remove metadata from relationship" onClick={() => this.removeMetadata()}><FontAwesomeIcon icon="times" size="sm" /></button>
</div>
);
}
@@ -206,15 +203,13 @@ export class LinkGroupEditor extends React.Component<LinkGroupEditorProps> {
constructor(props: LinkGroupEditorProps) {
super(props);
- const groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(StrCast(props.groupDoc.type));
- groupMdKeys.forEach(key => {
- this._metadataIds.set(key, Utils.GenerateGuid());
- });
+ const groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(StrCast(props.groupDoc.linkRelationship));
+ groupMdKeys.forEach(key => this._metadataIds.set(key, Utils.GenerateGuid()));
}
@action
setGroupType = (groupType: string): void => {
- this.props.groupDoc.type = groupType;
+ Doc.GetProto(this.props.groupDoc).linkRelationship = groupType;
}
removeGroupFromLink = (groupType: string): void => {
@@ -225,33 +220,6 @@ export class LinkGroupEditor extends React.Component<LinkGroupEditorProps> {
LinkManager.Instance.deleteGroupType(groupType);
}
- copyGroup = async (groupType: string): Promise<void> => {
- const sourceGroupDoc = this.props.groupDoc;
- const sourceMdDoc = await Cast(sourceGroupDoc.metadata, Doc);
- if (!sourceMdDoc) return;
-
- const destDoc = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc);
- // let destGroupList = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, destDoc);
- const keys = LinkManager.Instance.getMetadataKeysInGroup(groupType);
-
- // create new metadata doc with copied kvp
- const destMdDoc = new Doc();
- destMdDoc.anchor1 = StrCast(sourceMdDoc.anchor2);
- destMdDoc.anchor2 = StrCast(sourceMdDoc.anchor1);
- keys.forEach(key => {
- const val = sourceMdDoc[key] === undefined ? "" : StrCast(sourceMdDoc[key]);
- destMdDoc[key] = val;
- });
-
- // create new group doc with new metadata doc
- const destGroupDoc = new Doc();
- destGroupDoc.type = groupType;
- destGroupDoc.metadata = destMdDoc;
-
- if (destDoc) {
- LinkManager.Instance.addGroupToAnchor(this.props.linkDoc, destDoc, destGroupDoc, true);
- }
- }
@action
addMetadata = (groupType: string): void => {
@@ -270,69 +238,34 @@ export class LinkGroupEditor extends React.Component<LinkGroupEditorProps> {
renderMetadata = (): JSX.Element[] => {
const metadata: Array<JSX.Element> = [];
const groupDoc = this.props.groupDoc;
- const mdDoc = FieldValue(Cast(groupDoc.metadata, Doc));
- if (!mdDoc) {
- return [];
- }
- const groupType = StrCast(groupDoc.type);
+ const groupType = StrCast(groupDoc.linkRelationship);
const groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(groupType);
groupMdKeys.forEach((key) => {
- const val = StrCast(mdDoc[key]);
+ const val = StrCast(groupDoc[key]);
metadata.push(
- <LinkMetadataEditor key={"mded-" + this._metadataIds.get(key)} id={this._metadataIds.get(key)!} groupType={groupType} mdDoc={mdDoc} mdKey={key} mdValue={val} changeMdIdKey={this.changeMdIdKey} />
+ <LinkMetadataEditor key={"mded-" + this._metadataIds.get(key)} id={this._metadataIds.get(key)!} groupType={groupType} mdDoc={groupDoc} mdKey={key} mdValue={val} changeMdIdKey={this.changeMdIdKey} />
);
});
return metadata;
}
- viewGroupAsTable = (groupType: string): JSX.Element => {
- const keys = LinkManager.Instance.getMetadataKeysInGroup(groupType);
- const index = keys.indexOf("");
- if (index > -1) keys.splice(index, 1);
- const cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c, "#f1efeb"));
- const docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType);
- const createTable = action(() => Docs.Create.SchemaDocument(cols, docs, { _width: 500, _height: 300, title: groupType + " table" }));
- const ref = React.createRef<HTMLDivElement>();
- return <div ref={ref}><button className="linkEditor-button" onPointerDown={SetupDrag(ref, createTable)} title="Drag to view relationship table"><FontAwesomeIcon icon="table" size="sm" /></button></div>;
- }
-
render() {
- const groupType = StrCast(this.props.groupDoc.type);
+ const groupType = StrCast(this.props.groupDoc.linkRelationship);
// if ((groupType && LinkManager.Instance.getMetadataKeysInGroup(groupType).length > 0) || groupType === "") {
- let buttons;
- if (groupType === "") {
- buttons = (
- <>
- <button className="linkEditor-button" disabled={true} title="Add KVP"><FontAwesomeIcon icon="plus" size="sm" /></button>
- <button className="linkEditor-button" disabled title="Copy group to opposite anchor"><FontAwesomeIcon icon="exchange-alt" size="sm" /></button>
- <button className="linkEditor-button" onClick={() => this.removeGroupFromLink(groupType)} title="Remove group from link"><FontAwesomeIcon icon="times" size="sm" /></button>
- <button className="linkEditor-button" disabled title="Delete group"><FontAwesomeIcon icon="trash" size="sm" /></button>
- <button className="linkEditor-button" disabled title="Drag to view relationship table"><FontAwesomeIcon icon="table" size="sm" /></button>
- </>
- );
- } else {
- buttons = (
- <>
- <button className="linkEditor-button" onClick={() => this.addMetadata(groupType)} title="Add KVP"><FontAwesomeIcon icon="plus" size="sm" /></button>
- <button className="linkEditor-button" onClick={() => this.copyGroup(groupType)} title="Copy group to opposite anchor"><FontAwesomeIcon icon="exchange-alt" size="sm" /></button>
- <button className="linkEditor-button" onClick={() => this.removeGroupFromLink(groupType)} title="Remove group from link"><FontAwesomeIcon icon="times" size="sm" /></button>
- <button className="linkEditor-button" onClick={() => this.deleteGroup(groupType)} title="Delete group"><FontAwesomeIcon icon="trash" size="sm" /></button>
- {this.viewGroupAsTable(groupType)}
- </>
- );
- }
+ let buttons = <button className="linkEditor-button" disabled={groupType === ""} onClick={() => this.deleteGroup(groupType)} title="Delete Relationship from all links"><FontAwesomeIcon icon="trash" size="sm" /></button>;
+ let addButton = <button className="linkEditor-addbutton" onClick={() => this.addMetadata(groupType)} disabled={groupType === ""} title="Add metadata to relationship"><FontAwesomeIcon icon="plus" size="sm" /></button>;
+
return (
<div className="linkEditor-group">
<div className="linkEditor-group-row ">
- <p className="linkEditor-group-row-label">type:</p>
+ {buttons}
<GroupTypesDropdown groupType={groupType} setGroupType={this.setGroupType} />
+ <button className="linkEditor-button" onClick={() => this.removeGroupFromLink(groupType)} title="Remove relationship from link"><FontAwesomeIcon icon="times" size="sm" /></button>
</div>
{this.renderMetadata().length > 0 ? <p className="linkEditor-group-row-label">metadata:</p> : <></>}
+ {addButton}
{this.renderMetadata()}
- <div className="linkEditor-group-buttons">
- {buttons}
- </div>
</div>
);
}
@@ -343,6 +276,7 @@ interface LinkEditorProps {
sourceDoc: Doc;
linkDoc: Doc;
showLinks: () => void;
+ hideback?: boolean;
}
@observer
export class LinkEditor extends React.Component<LinkEditorProps> {
@@ -353,48 +287,23 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
this.props.showLinks();
}
- @action
- addGroup = (): void => {
- // create new metadata document for group
- const mdDoc = new Doc();
- mdDoc.anchor1 = this.props.sourceDoc.title;
- const opp = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc);
- if (opp) {
- mdDoc.anchor2 = opp.title;
- }
-
- // create new group document
- const groupDoc = new Doc();
- groupDoc.type = "";
- groupDoc.metadata = mdDoc;
-
- LinkManager.Instance.addGroupToAnchor(this.props.linkDoc, this.props.sourceDoc, groupDoc);
- }
-
render() {
const destination = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc);
- const groupList = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, this.props.sourceDoc);
- const groups = groupList.map(groupDoc => {
- return <LinkGroupEditor key={"gred-" + StrCast(groupDoc.type)} linkDoc={this.props.linkDoc} sourceDoc={this.props.sourceDoc} groupDoc={groupDoc} />;
+ const groups = [this.props.linkDoc].map(groupDoc => {
+ return <LinkGroupEditor key={"gred-" + StrCast(groupDoc.linkRelationship)} linkDoc={this.props.linkDoc} sourceDoc={this.props.sourceDoc} groupDoc={groupDoc} />;
});
- if (destination) {
- return (
- <div className="linkEditor">
- <button className="linkEditor-back" onPointerDown={() => this.props.showLinks()}><FontAwesomeIcon icon="arrow-left" size="sm" /></button>
- <div className="linkEditor-info">
- <p className="linkEditor-linkedTo">editing link to: <b>{destination.proto!.title}</b></p>
- <button className="linkEditor-button" onPointerDown={() => this.deleteLink()} title="Delete link"><FontAwesomeIcon icon="trash" size="sm" /></button>
- </div>
- <div className="linkEditor-groupsLabel">
- <b>Relationships:</b>
- <button className="linkEditor-button" onClick={() => this.addGroup()} title=" Add Group"><FontAwesomeIcon icon="plus" size="sm" /></button>
- </div>
- {groups.length > 0 ? groups : <div className="linkEditor-group">There are currently no relationships associated with this link.</div>}
+ return !destination ? (null) : (
+ <div className="linkEditor">
+ {this.props.hideback ? (null) : <button className="linkEditor-back" onPointerDown={() => this.props.showLinks()}><FontAwesomeIcon icon="arrow-left" size="sm" /></button>}
+ <div className="linkEditor-info">
+ <p className="linkEditor-linkedTo">editing link to: <b>{destination.proto!.title}</b></p>
+ <button className="linkEditor-button" onPointerDown={() => this.deleteLink()} title="Delete link"><FontAwesomeIcon icon="trash" size="sm" /></button>
</div>
+ {groups.length > 0 ? groups : <div className="linkEditor-group">There are currently no relationships associated with this link.</div>}
+ </div>
- );
- }
+ );
}
} \ No newline at end of file
diff --git a/src/client/views/linking/LinkFollowBox.scss b/src/client/views/linking/LinkFollowBox.scss
deleted file mode 100644
index 9eeed1cc8..000000000
--- a/src/client/views/linking/LinkFollowBox.scss
+++ /dev/null
@@ -1,93 +0,0 @@
-@import "../globalCssVariables";
-
-.linkFollowBox-main {
- position: absolute;
- background: whitesmoke;
- color: grey;
- border-radius: 15px;
- box-shadow: $intermediate-color 0.2vw 0.2vw 0.4vw;
- border: solid #BBBBBBBB 5px;
- pointer-events: all;
-
- .linkFollowBox-header {
- height: 50px;
- text-align: center;
- text-transform: uppercase;
- letter-spacing: 2px;
- font-size: 16px;
- width: 100%;
- }
-
- .direction-indicator {
- font-size: 12px;
- }
-
- .closeDocument {
- position: relative;
- max-width: 30px;
- top: -20px;
- left: 460px;
- color: $darker-alt-accent
- }
-
- .closeDocument:hover {
- color: $main-accent;
- }
-
- .topHeader {
- width: 100%;
- height: 25px;
- }
-
- .linkFollowBox-footer {
- height: 50px;
- text-align: center;
- display: flex;
- justify-content: center;
- align-items: center;
-
- button {
- background-color: $darker-alt-accent;
- width: 30%;
- }
- }
-
- .linkFollowBox-content {
- display: grid;
- grid-template-columns: 1fr 1fr 1fr;
- grid-column-gap: 5px;
- margin-left: 5px;
- margin-right: 5px;
-
- .linkFollowBox-item {
- background-color: $light-color;
- width: 100%;
- height: 100%;
-
- .linkFollowBox-itemContent {
- padding: 5px;
- font-size: 12px;
- overflow: scroll;
-
- input[type=radio] {
- border: 0px;
- margin-right: 5px;
- }
- }
-
- .title {
- display: flex;
- justify-content: center;
- align-items: center;
- text-transform: uppercase;
- color: $light-color;
- background-color: $lighter-alt-accent;
- width: 100%;
- height: 30px;
- border-bottom: solid $darker-alt-accent 5px;
- font-size: 12px;
- text-align: center;
- }
- }
- }
-} \ No newline at end of file
diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx
deleted file mode 100644
index 325c92413..000000000
--- a/src/client/views/linking/LinkFollowBox.tsx
+++ /dev/null
@@ -1,571 +0,0 @@
-import { observable, computed, action, runInAction, reaction, IReactionDisposer } from "mobx";
-import React = require("react");
-import { observer } from "mobx-react";
-import { FieldViewProps, FieldView } from "../nodes/FieldView";
-import { Doc, DocListCastAsync, Opt } from "../../../new_fields/Doc";
-import { undoBatch } from "../../util/UndoManager";
-import { NumCast, FieldValue, Cast, StrCast } from "../../../new_fields/Types";
-import { CollectionViewType } from "../collections/CollectionView";
-import { CollectionDockingView } from "../collections/CollectionDockingView";
-import { SelectionManager } from "../../util/SelectionManager";
-import { DocumentManager } from "../../util/DocumentManager";
-import { DocumentView } from "../nodes/DocumentView";
-import "./LinkFollowBox.scss";
-import { SearchUtil } from "../../util/SearchUtil";
-import { Id } from "../../../new_fields/FieldSymbols";
-import { listSpec } from "../../../new_fields/Schema";
-import { DocServer } from "../../DocServer";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { faTimes } from '@fortawesome/free-solid-svg-icons';
-import { docs_v1 } from "googleapis";
-import { Utils } from "../../../Utils";
-import { Link } from "@react-pdf/renderer";
-
-enum FollowModes {
- OPENTAB = "Open in Tab",
- OPENRIGHT = "Open in Right Split",
- OPENFULL = "Open Full Screen",
- PAN = "Pan to Document",
- INPLACE = "Open In Place"
-}
-
-enum FollowOptions {
- ZOOM = "Zoom",
- NOZOOM = "No Zoom",
-}
-
-@observer
-export class LinkFollowBox extends React.Component<FieldViewProps> {
-
- public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LinkFollowBox, fieldKey); }
- public static Instance: LinkFollowBox | undefined;
- @observable static linkDoc: Doc | undefined = undefined;
- @observable static destinationDoc: Doc | undefined = undefined;
- @observable static sourceDoc: Doc | undefined = undefined;
- @observable selectedMode: string = "";
- @observable selectedContext: Doc | undefined = undefined;
- @observable selectedContextAliases: Doc[] | undefined = undefined;
- @observable selectedOption: string = "";
- @observable selectedContextString: string = "";
- @observable sourceView: DocumentView | undefined = undefined;
- @observable canPan: boolean = false;
- @observable shouldUseOnlyParentContext = false;
- _contextDisposer?: IReactionDisposer;
-
- @observable private _docs: { col: Doc, target: Doc }[] = [];
- @observable private _otherDocs: { col: Doc, target: Doc }[] = [];
-
- constructor(props: FieldViewProps) {
- super(props);
- LinkFollowBox.Instance = this;
- this.resetVars();
- this.props.Document.isBackground = true;
- }
-
- componentDidMount = () => {
- this.resetVars();
-
- this._contextDisposer = reaction(
- () => this.selectedContextString,
- async () => {
- const ref = await DocServer.GetRefField(this.selectedContextString);
- runInAction(() => {
- if (ref instanceof Doc) {
- this.selectedContext = ref;
- }
- });
- if (this.selectedContext instanceof Doc) {
- const aliases = await SearchUtil.GetViewsOfDocument(this.selectedContext);
- runInAction(() => { this.selectedContextAliases = aliases; });
- }
- }
- );
- }
-
- componentWillUnmount = () => {
- this._contextDisposer && this._contextDisposer();
- }
-
- async resetPan() {
- if (LinkFollowBox.destinationDoc && this.sourceView && this.sourceView.props.ContainingCollectionDoc) {
- runInAction(() => this.canPan = false);
- if (this.sourceView.props.ContainingCollectionDoc._viewType === CollectionViewType.Freeform) {
- const docs = Cast(this.sourceView.props.ContainingCollectionDoc.data, listSpec(Doc), []);
- const aliases = await SearchUtil.GetViewsOfDocument(Doc.GetProto(LinkFollowBox.destinationDoc));
-
- aliases.forEach(alias => {
- if (docs.filter(doc => doc === alias).length > 0) {
- runInAction(() => { this.canPan = true; });
- }
- });
- }
- }
- }
-
- @action
- resetVars = () => {
- this.selectedContext = undefined;
- this.selectedContextString = "";
- this.selectedMode = "";
- this.selectedOption = "";
- LinkFollowBox.linkDoc = undefined;
- LinkFollowBox.sourceDoc = undefined;
- LinkFollowBox.destinationDoc = undefined;
- this.sourceView = undefined;
- this.canPan = false;
- this.shouldUseOnlyParentContext = false;
- }
-
- async fetchDocuments() {
- if (LinkFollowBox.destinationDoc) {
- const dest: Doc = LinkFollowBox.destinationDoc;
- const aliases = await SearchUtil.GetViewsOfDocument(Doc.GetProto(dest));
- const { docs } = await SearchUtil.Search("", true, { fq: `data_l:"${dest[Id]}"` });
- const map: Map<Doc, Doc> = new Map;
- const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search("", true, { fq: `data_l:"${doc[Id]}"` }).then(result => result.docs)));
- allDocs.forEach((docs, index) => docs.forEach(doc => map.set(doc, aliases[index])));
- docs.forEach(doc => map.delete(doc));
- runInAction(async () => {
- this._docs = docs.filter(doc => !Doc.AreProtosEqual(doc, CollectionDockingView.Instance.props.Document)).map(doc => ({ col: doc, target: dest }));
- this._otherDocs = Array.from(map.entries()).filter(entry => !Doc.AreProtosEqual(entry[0], CollectionDockingView.Instance.props.Document)).map(([col, target]) => ({ col, target }));
- const tcontext = LinkFollowBox.linkDoc && (await Cast(LinkFollowBox.linkDoc.anchor2Context, Doc)) as Doc;
- runInAction(() => tcontext && this._docs.splice(0, 0, { col: tcontext, target: dest }));
- });
- }
- }
-
- @action
- setLinkDocs = (linkDoc: Doc, source: Doc, dest: Doc) => {
- this.resetVars();
-
- LinkFollowBox.linkDoc = linkDoc;
- LinkFollowBox.sourceDoc = source;
- LinkFollowBox.destinationDoc = dest;
- this.fetchDocuments();
-
- SelectionManager.SelectedDocuments().forEach(dv => {
- if (dv.props.Document === LinkFollowBox.sourceDoc) {
- this.sourceView = dv;
- }
- });
-
- this.resetPan();
- }
-
- highlightDoc = () => LinkFollowBox.destinationDoc && Doc.linkFollowHighlight(LinkFollowBox.destinationDoc);
-
- @undoBatch
- openFullScreen = () => {
- if (LinkFollowBox.destinationDoc) {
- const view = DocumentManager.Instance.getDocumentView(LinkFollowBox.destinationDoc);
- view && CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(view);
- }
- }
-
- @undoBatch
- openColFullScreen = (options: { context: Doc }) => {
- if (LinkFollowBox.destinationDoc) {
- if (NumCast(options.context._viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
- const newPanX = NumCast(LinkFollowBox.destinationDoc.x) + NumCast(LinkFollowBox.destinationDoc._width) / 2;
- const newPanY = NumCast(LinkFollowBox.destinationDoc.y) + NumCast(LinkFollowBox.destinationDoc._height) / 2;
- options.context._panX = newPanX;
- options.context._panY = newPanY;
- }
- const view = DocumentManager.Instance.getDocumentView(options.context);
- view && CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(view);
- this.highlightDoc();
- }
- }
-
- // should container be a doc or documentview or what? This one needs work and is more long term
- @undoBatch
- openInContainer = (options: { container: Doc }) => {
-
- }
-
- static _addDocTab: (undefined | ((doc: Doc, dataDoc: Opt<Doc>, where: string) => boolean));
-
- static setAddDocTab = (addFunc: (doc: Doc, dataDoc: Opt<Doc>, where: string) => boolean) => {
- LinkFollowBox._addDocTab = addFunc;
- }
-
- @undoBatch
- openLinkColRight = (options: { context: Doc, shouldZoom: boolean }) => {
- if (LinkFollowBox.destinationDoc) {
- options.context = Doc.IsPrototype(options.context) ? Doc.MakeDelegate(options.context) : options.context;
- if (NumCast(options.context._viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
- const newPanX = NumCast(LinkFollowBox.destinationDoc.x) + NumCast(LinkFollowBox.destinationDoc._width) / 2;
- const newPanY = NumCast(LinkFollowBox.destinationDoc.y) + NumCast(LinkFollowBox.destinationDoc._height) / 2;
- options.context._panX = newPanX;
- options.context._panY = newPanY;
- }
- (LinkFollowBox._addDocTab || this.props.addDocTab)(options.context, undefined, "onRight");
-
- if (options.shouldZoom) this.jumpToLink({ shouldZoom: options.shouldZoom });
-
- this.highlightDoc();
- SelectionManager.DeselectAll();
- }
- }
-
- @undoBatch
- openLinkRight = () => {
- if (LinkFollowBox.destinationDoc) {
- const alias = Doc.MakeAlias(LinkFollowBox.destinationDoc);
- (LinkFollowBox._addDocTab || this.props.addDocTab)(alias, undefined, "onRight");
- this.highlightDoc();
- SelectionManager.DeselectAll();
- }
-
- }
-
- @undoBatch
- jumpToLink = async (options: { shouldZoom: boolean }) => {
- if (LinkFollowBox.sourceDoc && LinkFollowBox.linkDoc) {
- const focus = (document: Doc) => { (LinkFollowBox._addDocTab || this.props.addDocTab)(document, undefined, "inTab"); SelectionManager.DeselectAll(); };
- //let focus = (doc: Doc, maxLocation: string) => this.props.focus(docthis.props.focus(LinkFollowBox.destinationDoc, true, 1, () => this.props.addDocTab(doc, undefined, maxLocation));
-
- DocumentManager.Instance.FollowLink(LinkFollowBox.linkDoc, LinkFollowBox.sourceDoc, focus, options && options.shouldZoom, false, undefined);
- }
- }
-
- @undoBatch
- openLinkTab = () => {
- if (LinkFollowBox.destinationDoc) {
- const fullScreenAlias = Doc.MakeAlias(LinkFollowBox.destinationDoc);
- // this.prosp.addDocTab is empty -- use the link source's addDocTab
- (LinkFollowBox._addDocTab || this.props.addDocTab)(fullScreenAlias, undefined, "inTab");
-
- this.highlightDoc();
- SelectionManager.DeselectAll();
- }
- }
-
- @undoBatch
- openLinkColTab = (options: { context: Doc, shouldZoom: boolean }) => {
- if (LinkFollowBox.destinationDoc) {
- options.context = Doc.IsPrototype(options.context) ? Doc.MakeDelegate(options.context) : options.context;
- if (NumCast(options.context._viewType, CollectionViewType.Invalid) === CollectionViewType.Freeform) {
- const newPanX = NumCast(LinkFollowBox.destinationDoc.x) + NumCast(LinkFollowBox.destinationDoc._width) / 2;
- const newPanY = NumCast(LinkFollowBox.destinationDoc.y) + NumCast(LinkFollowBox.destinationDoc._height) / 2;
- options.context._panX = newPanX;
- options.context._panY = newPanY;
- }
- (LinkFollowBox._addDocTab || this.props.addDocTab)(options.context, undefined, "inTab");
- if (options.shouldZoom) this.jumpToLink({ shouldZoom: options.shouldZoom });
-
- this.highlightDoc();
- SelectionManager.DeselectAll();
- }
- }
-
- @undoBatch
- openLinkInPlace = (options: { shouldZoom: boolean }) => {
-
- if (LinkFollowBox.destinationDoc && LinkFollowBox.sourceDoc) {
- if (this.sourceView && this.sourceView.props.addDocument) {
- const destViews = DocumentManager.Instance.getDocumentViews(LinkFollowBox.destinationDoc);
- if (!destViews.find(dv => dv.props.ContainingCollectionView === this.sourceView!.props.ContainingCollectionView)) {
- const alias = Doc.MakeAlias(LinkFollowBox.destinationDoc);
- const y = NumCast(LinkFollowBox.sourceDoc.y);
- const x = NumCast(LinkFollowBox.sourceDoc.x);
-
- const width = NumCast(LinkFollowBox.sourceDoc._width);
- const height = NumCast(LinkFollowBox.sourceDoc._height);
-
- alias.x = x + width + 30;
- alias.y = y;
- alias._width = width;
- alias._height = height;
-
- this.sourceView.props.addDocument(alias);
- }
- }
-
- this.jumpToLink({ shouldZoom: options.shouldZoom });
-
- this.highlightDoc();
- SelectionManager.DeselectAll();
- }
- }
-
- //set this to be the default link behavior, can be any of the above
- public defaultLinkBehavior: (options?: any) => void = this.jumpToLink;
-
- @action
- currentLinkBehavior = () => {
- // this.resetPan();
- if (LinkFollowBox.destinationDoc) {
- if (this.selectedContextString === "") {
- this.selectedContextString = "self";
- this.selectedContext = LinkFollowBox.destinationDoc;
- }
- if (this.selectedOption === "") this.selectedOption = FollowOptions.NOZOOM;
- const shouldZoom: boolean = this.selectedOption === FollowOptions.NOZOOM ? false : true;
- const notOpenInContext: boolean = this.selectedContextString === "self" || this.selectedContextString === LinkFollowBox.destinationDoc[Id];
-
- if (this.selectedMode === FollowModes.INPLACE) {
- if (shouldZoom !== undefined) this.openLinkInPlace({ shouldZoom: shouldZoom });
- }
- else if (this.selectedMode === FollowModes.OPENFULL) {
- if (notOpenInContext) this.openFullScreen();
- else this.selectedContext && this.openColFullScreen({ context: this.selectedContext });
- }
- else if (this.selectedMode === FollowModes.OPENRIGHT) {
- if (notOpenInContext) this.openLinkRight();
- else this.selectedContext && this.openLinkColRight({ context: this.selectedContext, shouldZoom: shouldZoom });
- }
- else if (this.selectedMode === FollowModes.OPENTAB) {
- if (notOpenInContext) this.openLinkTab();
- else this.selectedContext && this.openLinkColTab({ context: this.selectedContext, shouldZoom: shouldZoom });
- }
- else if (this.selectedMode === FollowModes.PAN) {
- this.jumpToLink({ shouldZoom: shouldZoom });
- }
- else return;
- }
- }
-
- @action
- handleModeChange = (e: React.ChangeEvent) => {
- const target = e.target as HTMLInputElement;
- this.selectedMode = target.value;
- this.selectedContext = undefined;
- this.selectedContextString = "";
-
- this.shouldUseOnlyParentContext = (this.selectedMode === FollowModes.INPLACE || this.selectedMode === FollowModes.PAN);
-
- if (this.shouldUseOnlyParentContext) {
- if (this.sourceView && this.sourceView.props.ContainingCollectionDoc) {
- this.selectedContext = this.sourceView.props.ContainingCollectionDoc;
- this.selectedContextString = (StrCast(this.sourceView.props.ContainingCollectionDoc.title));
- }
- }
- }
-
- @action
- handleOptionChange = (e: React.ChangeEvent) => {
- const target = e.target as HTMLInputElement;
- this.selectedOption = target.value;
- }
-
- @action
- handleContextChange = (e: React.ChangeEvent) => {
- const target = e.target as HTMLInputElement;
- this.selectedContextString = target.value;
- // selectedContext is updated in reaction
- this.selectedOption = "";
- }
-
- @computed
- get canOpenInPlace() {
- if (this.sourceView && this.sourceView.props.ContainingCollectionDoc) {
- const colDoc = this.sourceView.props.ContainingCollectionDoc;
- if (colDoc._viewType === CollectionViewType.Freeform) return true;
- }
- return false;
- }
-
- @computed
- get availableModes() {
- return (
- <div>
- <label><input
- type="radio"
- name="mode"
- value={FollowModes.OPENRIGHT}
- checked={this.selectedMode === FollowModes.OPENRIGHT}
- onChange={this.handleModeChange}
- disabled={false} />
- {FollowModes.OPENRIGHT}
- </label><br />
- <label><input
- type="radio"
- name="mode"
- value={FollowModes.OPENTAB}
- checked={this.selectedMode === FollowModes.OPENTAB}
- onChange={this.handleModeChange}
- disabled={false} />
- {FollowModes.OPENTAB}
- </label><br />
- <label><input
- type="radio"
- name="mode"
- value={FollowModes.OPENFULL}
- checked={this.selectedMode === FollowModes.OPENFULL}
- onChange={this.handleModeChange}
- disabled={false} />
- {FollowModes.OPENFULL}
- </label><br />
- <label><input
- type="radio"
- name="mode"
- value={FollowModes.PAN}
- checked={this.selectedMode === FollowModes.PAN}
- onChange={this.handleModeChange}
- disabled={!this.canPan} />
- {FollowModes.PAN}
- </label><br />
- <label><input
- type="radio"
- name="mode"
- value={FollowModes.INPLACE}
- checked={this.selectedMode === FollowModes.INPLACE}
- onChange={this.handleModeChange}
- disabled={!this.canOpenInPlace} />
- {FollowModes.INPLACE}
- </label><br />
- </div>
- );
- }
-
- @computed
- get parentName() {
- if (this.sourceView && this.sourceView.props.ContainingCollectionDoc) {
- return this.sourceView.props.ContainingCollectionDoc.title;
- }
- }
-
- @computed
- get parentID(): string {
- if (this.sourceView && this.sourceView.props.ContainingCollectionDoc) {
- return StrCast(this.sourceView.props.ContainingCollectionDoc[Id]);
- }
- return "col";
- }
-
- @computed
- get availableContexts() {
- return (
- this.shouldUseOnlyParentContext ?
- <label><input
- type="radio" disabled={true}
- name="context"
- value={this.parentID}
- checked={true} />
- {this.parentName} (Parent Collection)
- </label>
- :
- <div>
- <label><input
- type="radio" disabled={LinkFollowBox.linkDoc ? false : true}
- name="context"
- value={LinkFollowBox.destinationDoc ? StrCast(LinkFollowBox.destinationDoc[Id]) : "self"}
- checked={LinkFollowBox.destinationDoc ? this.selectedContextString === StrCast(LinkFollowBox.destinationDoc[Id]) || this.selectedContextString === "self" : true}
- onChange={this.handleContextChange} />
- Open Self
- </label><br />
- {[...this._docs, ...this._otherDocs].map(doc => {
- if (doc && doc.target && doc.col.title !== "Recently Closed") {
- return <div key={doc.col[Id] + doc.target[Id]}><label key={doc.col[Id] + doc.target[Id]}>
- <input
- type="radio" disabled={LinkFollowBox.linkDoc ? false : true}
- name="context"
- value={StrCast(doc.col[Id])}
- checked={this.selectedContextString === StrCast(doc.col[Id])}
- onChange={this.handleContextChange} />
- {doc.col.title}
- </label><br /></div>;
- }
- })}
- </div>
- );
- }
-
- @computed
- get shouldShowZoom(): boolean {
- if (this.selectedMode === FollowModes.OPENFULL) return false;
- if (this.shouldUseOnlyParentContext) return true;
- if (LinkFollowBox.destinationDoc ? this.selectedContextString === LinkFollowBox.destinationDoc[Id] : "self") return false;
-
- let contextMatch: boolean = false;
- if (this.selectedContextAliases) {
- this.selectedContextAliases.forEach(alias => {
- if (alias._viewType === CollectionViewType.Freeform) contextMatch = true;
- });
- }
- if (contextMatch) return true;
-
- return false;
- }
-
- @computed
- get availableOptions() {
- if (LinkFollowBox.destinationDoc) {
- return (
- this.shouldShowZoom ?
- <div>
- <label><input
- type="radio"
- name="option"
- value={FollowOptions.ZOOM}
- checked={this.selectedOption === FollowOptions.ZOOM}
- onChange={this.handleOptionChange}
- disabled={false} />
- {FollowOptions.ZOOM}
- </label><br />
- <label><input
- type="radio"
- name="option"
- value={FollowOptions.NOZOOM}
- checked={this.selectedOption === FollowOptions.NOZOOM}
- onChange={this.handleOptionChange}
- disabled={false} />
- {FollowOptions.NOZOOM}
- </label><br />
- </div>
- :
- <div>No Available Options</div>
- );
- }
- return null;
- }
-
- render() {
- return (
- <div className="linkFollowBox-main" style={{ height: NumCast(this.props.Document._height), width: NumCast(this.props.Document._width) }}>
- <div className="linkFollowBox-header">
- <div className="topHeader">
- {LinkFollowBox.linkDoc ? "Link Title: " + StrCast(LinkFollowBox.linkDoc.title) : "No Link Selected"}
- <div onClick={() => this.props.Document.isMinimized = true} 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>
- <div className="linkFollowBox-content" style={{ height: NumCast(this.props.Document._height) - 110 }}>
- <div className="linkFollowBox-item">
- <div className="linkFollowBox-item title">Mode</div>
- <div className="linkFollowBox-itemContent">
- {LinkFollowBox.linkDoc ? this.availableModes : "Please select a link to view modes"}
- </div>
- </div>
- <div className="linkFollowBox-item">
- <div className="linkFollowBox-item title">Context</div>
- <div className="linkFollowBox-itemContent">
- {this.selectedMode !== "" ? this.availableContexts : "Please select a mode to view contexts"}
- </div>
- </div>
- <div className="linkFollowBox-item">
- <div className="linkFollowBox-item title">Options</div>
- <div className="linkFollowBox-itemContent">
- {this.selectedContextString !== "" ? this.availableOptions : "Please select a context to view options"}
- </div>
- </div>
- </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
- </button>
- </div>
- </div>
- );
- }
-} \ No newline at end of file
diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx
index 1a40f0c55..b768eacc3 100644
--- a/src/client/views/linking/LinkMenu.tsx
+++ b/src/client/views/linking/LinkMenu.tsx
@@ -16,7 +16,7 @@ library.add(faTrash);
interface Props {
docView: DocumentView;
changeFlyout: () => void;
- addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean;
+ addDocTab: (document: Doc, where: string) => boolean;
}
@observer
@@ -60,7 +60,7 @@ export class LinkMenu extends React.Component<Props> {
if (this._editingLink === undefined) {
return (
<div className="linkMenu">
- <button className="linkEditor-button linkEditor-clearButton" onClick={() => this.clearAllLinks()} title="Clear all links"><FontAwesomeIcon icon="trash" size="sm" /></button>
+ {/* <button className="linkEditor-button linkEditor-clearButton" onClick={() => this.clearAllLinks()} title="Clear all links"><FontAwesomeIcon icon="trash" size="sm" /></button> */}
{/* <input id="linkMenu-searchBar" type="text" placeholder="Search..."></input> */}
<div className="linkMenu-list">
{this.renderAllGroups(groups)}
diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx
index 0c38ff45c..88f837a03 100644
--- a/src/client/views/linking/LinkMenuGroup.tsx
+++ b/src/client/views/linking/LinkMenuGroup.tsx
@@ -17,7 +17,7 @@ interface LinkMenuGroupProps {
group: Doc[];
groupType: string;
showEditor: (linkDoc: Doc) => void;
- addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean;
+ addDocTab: (document: Doc, where: string) => boolean;
docView: DocumentView;
}
@@ -58,7 +58,7 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
if (index > -1) keys.splice(index, 1);
const cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c, "#f1efeb"));
const docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType);
- const createTable = action(() => Docs.Create.SchemaDocument(cols, docs, { _width: 500, _height: 300, title: groupType + " table" }));
+ const createTable = action(() => Docs.Create.SchemaDocument(cols, docs, { _width: 500, _height: 300, title: groupType + " table", childDropAction: "alias" }));
const ref = React.createRef<HTMLDivElement>();
return <div ref={ref}><button className="linkEditor-button linkEditor-tableButton" onPointerDown={SetupDrag(ref, createTable)} title="Drag to view relationship table"><FontAwesomeIcon icon="table" size="sm" /></button></div>;
}
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index b7d27ee30..5fd6e4630 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -8,9 +8,10 @@ import { Cast, StrCast } from '../../../new_fields/Types';
import { DragManager } from '../../util/DragManager';
import { LinkManager } from '../../util/LinkManager';
import { ContextMenu } from '../ContextMenu';
-import { LinkFollowBox } from './LinkFollowBox';
import './LinkMenuItem.scss';
import React = require("react");
+import { DocumentManager } from '../../util/DocumentManager';
+import { setupMoveUpEvents, emptyFunction } from '../../../Utils';
library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp);
@@ -20,7 +21,7 @@ interface LinkMenuItemProps {
sourceDoc: Doc;
destinationDoc: Doc;
showEditor: (linkDoc: Doc) => void;
- addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean;
+ addDocTab: (document: Doc, where: string) => boolean;
}
@observer
@@ -29,29 +30,28 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
private _downX = 0;
private _downY = 0;
private _eleClone: any;
+
+ _editRef = React.createRef<HTMLDivElement>();
@observable private _showMore: boolean = false;
- @action toggleShowMore() { this._showMore = !this._showMore; }
+ @action toggleShowMore(e: React.PointerEvent) { e.stopPropagation(); this._showMore = !this._showMore; }
onEdit = (e: React.PointerEvent): void => {
- e.stopPropagation();
- this.props.showEditor(this.props.linkDoc);
- //SelectionManager.DeselectAll();
+ setupMoveUpEvents(this, e, this.editMoved, emptyFunction, () => this.props.showEditor(this.props.linkDoc));
+ }
+
+ editMoved = (e: PointerEvent) => {
+ DragManager.StartDocumentDrag([this._editRef.current!], new DragManager.DocumentDragData([this.props.linkDoc]), e.x, e.y);
+ return true;
}
renderMetadata = (): JSX.Element => {
- const groups = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, this.props.sourceDoc);
- const index = groups.findIndex(groupDoc => StrCast(groupDoc.type).toUpperCase() === this.props.groupType.toUpperCase());
- const groupDoc = index > -1 ? groups[index] : undefined;
+ const index = StrCast(this.props.linkDoc.title).toUpperCase() === this.props.groupType.toUpperCase() ? 0 : -1;
+ const mdDoc = index > -1 ? this.props.linkDoc : undefined;
let mdRows: Array<JSX.Element> = [];
- if (groupDoc) {
- const mdDoc = Cast(groupDoc.metadata, Doc, null);
- if (mdDoc) {
- const keys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);//groupMetadataKeys.get(this.props.groupType);
- mdRows = keys.map(key => {
- return (<div key={key} className="link-metadata-row"><b>{key}</b>: {StrCast(mdDoc[key])}</div>);
- });
- }
+ if (mdDoc) {
+ const keys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);//groupMetadataKeys.get(this.props.groupType);
+ mdRows = keys.map(key => <div key={key} className="link-metadata-row"><b>{key}</b>: {StrCast(mdDoc[key])}</div>);
}
return (<div className="link-metadata">{mdRows}</div>);
@@ -72,11 +72,6 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
document.removeEventListener("pointermove", this.onLinkButtonMoved);
document.removeEventListener("pointerup", this.onLinkButtonUp);
- if (LinkFollowBox.Instance !== undefined) {
- LinkFollowBox.Instance.props.Document.isMinimized = false;
- LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
- LinkFollowBox.setAddDocTab(this.props.addDocTab);
- }
e.stopPropagation();
}
@@ -93,26 +88,13 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
onContextMenu = (e: React.MouseEvent) => {
e.preventDefault();
- ContextMenu.Instance.addItem({ description: "Open in Link Follower", event: () => this.openLinkFollower(), icon: "link" });
ContextMenu.Instance.addItem({ description: "Follow Default Link", event: () => this.followDefault(), icon: "arrow-right" });
ContextMenu.Instance.displayMenu(e.clientX, e.clientY);
}
@action.bound
async followDefault() {
- if (LinkFollowBox.Instance !== undefined) {
- LinkFollowBox.setAddDocTab(this.props.addDocTab);
- LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
- LinkFollowBox.Instance.defaultLinkBehavior();
- }
- }
-
- @action.bound
- async openLinkFollower() {
- if (LinkFollowBox.Instance !== undefined) {
- LinkFollowBox.Instance.props.Document.isMinimized = false;
- LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
- }
+ DocumentManager.Instance.FollowLink(this.props.linkDoc, this.props.sourceDoc, doc => this.props.addDocTab(doc, "onRight"), false);
}
render() {
@@ -125,9 +107,9 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
<div ref={this._drag} className="linkMenu-name" title="drag to view target. click to customize." onPointerDown={this.onLinkButtonDown}>
<p >{StrCast(this.props.destinationDoc.title)}</p>
<div className="linkMenu-item-buttons">
- {canExpand ? <div title="Show more" className="button" onPointerDown={() => this.toggleShowMore()}>
+ {canExpand ? <div title="Show more" className="button" onPointerDown={e => this.toggleShowMore(e)}>
<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>
+ <div title="Edit link" className="button" ref={this._editRef} onPointerDown={this.onEdit}><FontAwesomeIcon className="fa-icon" icon="edit" 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>