aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2020-11-03 21:40:53 -0500
committerbobzel <zzzman@gmail.com>2020-11-03 21:40:53 -0500
commitf23e2f2bcb6ab7fb1895a87a34f8eafcbab90a8d (patch)
treec8339d70f620f13d7af5bbb8ea6f2812a0f9cf95 /src
parenta43c3c014c3e7bbdfbee8bf234a5812d1601b945 (diff)
fixed LinkManager to cache links correctly. fixes issue with linkButton not showing the correct number.
Diffstat (limited to 'src')
-rw-r--r--src/client/util/LinkManager.ts28
-rw-r--r--src/client/views/nodes/DocumentLinksButton.tsx109
-rw-r--r--src/client/views/nodes/DocumentView.tsx2
3 files changed, 57 insertions, 82 deletions
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index c3ab7c6e7..3a0c0e3eb 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -22,47 +22,41 @@ import { computedFn } from "mobx-utils";
export class LinkManager {
private static _instance: LinkManager;
-
public static currentLink: Opt<Doc>;
-
public static get Instance(): LinkManager { return this._instance || (this._instance = new this()); }
public addLink(linkDoc: Doc) { return Doc.AddDocToList(Doc.LinkDBDoc(), "data", linkDoc); }
-
public deleteLink(linkDoc: Doc) { return Doc.RemoveDocFromList(Doc.LinkDBDoc(), "data", linkDoc); }
-
- public deleteAllLinksOnAnchor(anchor: Doc) { LinkManager.Instance.getAllRelatedLinks(anchor).forEach(linkDoc => LinkManager.Instance.deleteLink(linkDoc)); }
+ public deleteAllLinksOnAnchor(anchor: Doc) { LinkManager.Instance.relatedLinker(anchor).forEach(linkDoc => LinkManager.Instance.deleteLink(linkDoc)); }
public getAllRelatedLinks(anchor: Doc) { return this.relatedLinker(anchor); } // finds all links that contain the given anchor
-
public getAllDirectLinks(anchor: Doc): Doc[] { return this.directLinker(anchor); } // finds all links that contain the given anchor
-
public getAllLinks(): Doc[] { return this.allLinks(); }
- allLinks = computedFn(function allLinks(this: any) {
+ allLinks = computedFn(function allLinks(this: any): Doc[] {
const lset = new Set<Doc>(DocListCast(Doc.LinkDBDoc().data));
SharingManager.Instance.users.forEach(user => DocListCast(user.linkDatabase?.data).map(doc => lset.add(doc)));
return Array.from(lset);
}, true);
- directLinker = computedFn(function directLinker(this: any, anchor: Doc) {
- return LinkManager.Instance.getAllLinks().filter(link => {
+ directLinker = computedFn(function directLinker(this: any, anchor: Doc): Doc[] {
+ return LinkManager.Instance.allLinks().filter(link => {
const a1 = Cast(link?.anchor1, Doc, null);
const a2 = Cast(link?.anchor2, Doc, null);
return link && ((a1?.author !== undefined && a2?.author !== undefined) || link.author === Doc.CurrentUserEmail) && (Doc.AreProtosEqual(anchor, a1) || Doc.AreProtosEqual(anchor, a2) || Doc.AreProtosEqual(link, anchor));
});
}, true);
- relatedLinker = computedFn(function relatedLinker(this: any, anchor: Doc) {
- const related = LinkManager.Instance.directLinker(anchor);
- DocListCast(anchor[Doc.LayoutFieldKey(anchor) + "-annotations"]).map(anno => related.push(...LinkManager.Instance.getAllRelatedLinks(anno)));
- return related;
+ relatedLinker = computedFn(function relatedLinker(this: any, anchor: Doc): Doc[] {
+ return DocListCast(anchor[Doc.LayoutFieldKey(anchor) + "-annotations"]).reduce((list, anno) =>
+ [...list, ...LinkManager.Instance.relatedLinker(anno)],
+ LinkManager.Instance.directLinker(anchor).slice());
}, true);
// returns map of group type to anchor's links in that group type
public getRelatedGroupedLinks(anchor: Doc): Map<string, Array<Doc>> {
const anchorGroups = new Map<string, Array<Doc>>();
- this.getAllRelatedLinks(anchor).forEach(link => {
+ this.relatedLinker(anchor).forEach(link => {
if (!link.linkRelationship || link?.linkRelationship !== "-ungrouped-") {
const group = anchorGroups.get(StrCast(link.linkRelationship));
anchorGroups.set(StrCast(link.linkRelationship), group ? [...group, link] : [link]);
@@ -78,13 +72,13 @@ export class LinkManager {
// returns a list of all metadata docs associated with the given group type
public getAllMetadataDocsInGroup(groupType: string): Array<Doc> {
const md: Doc[] = [];
- LinkManager.Instance.getAllLinks().forEach(linkDoc => StrCast(linkDoc.linkRelationship).toUpperCase() === groupType.toUpperCase() && md.push(linkDoc));
+ LinkManager.Instance.allLinks().forEach(linkDoc => StrCast(linkDoc.linkRelationship).toUpperCase() === groupType.toUpperCase() && md.push(linkDoc));
return md;
}
// checks if a link with the given anchors exists
public doesLinkExist(anchor1: Doc, anchor2: Doc): boolean {
- return -1 !== LinkManager.Instance.getAllLinks().findIndex(linkDoc =>
+ return -1 !== LinkManager.Instance.allLinks().findIndex(linkDoc =>
(Doc.AreProtosEqual(Cast(linkDoc.anchor1, Doc, null), anchor1) && Doc.AreProtosEqual(Cast(linkDoc.anchor2, Doc, null), anchor2)) ||
(Doc.AreProtosEqual(Cast(linkDoc.anchor1, Doc, null), anchor2) && Doc.AreProtosEqual(Cast(linkDoc.anchor2, Doc, null), anchor1)));
}
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index a167f2a23..95c007175 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -3,7 +3,6 @@ import { Tooltip } from "@material-ui/core";
import { action, computed, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
import { Doc, DocListCast, Opt } from "../../../fields/Doc";
-import { DocumentType } from "../../documents/DocumentTypes";
import { emptyFunction, setupMoveUpEvents, returnFalse, Utils, emptyPath } from "../../../Utils";
import { TraceMobx } from "../../../fields/util";
import { DocUtils, Docs } from "../../documents/Documents";
@@ -39,6 +38,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
@observable public static StartLinkView: DocumentView | undefined;
@observable public static AnnotationId: string | undefined;
@observable public static AnnotationUri: string | undefined;
+ @observable public static EditLink: DocumentView | undefined;
@observable public static invisibleWebDoc: Opt<Doc>;
public static invisibleWebRef = React.createRef<HTMLDivElement>();
@@ -209,94 +209,75 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
}
}));
- @observable
- public static EditLink: DocumentView | undefined;
@action clearLinks() {
DocumentLinksButton.StartLink = undefined;
DocumentLinksButton.StartLinkView = undefined;
}
- @computed
- get linkButton() {
- TraceMobx();
- const links = DocUtils.FilterDocs(Array.from(new Set<Doc>(this.props.links)), this.props.View.props.docFilters(), []);
-
- const menuTitle = this.props.StartLink ? "Drag or tap to start link" : "Tap to complete link";
- const buttonTitle = "Tap to view links";
- const title = this.props.InMenu ? menuTitle : buttonTitle;
-
-
- const startLink = <img
- style={{ width: "11px", height: "11px" }}
- id={"startLink-icon"}
- src={`/assets/${"startLink.png"}`} />;
-
- const endLink = <img
- style={{ width: "14px", height: "9px" }}
- id={"endLink-icon"}
- src={`/assets/${"endLink.png"}`} />;
+ @computed get filteredLinks() {
+ return DocUtils.FilterDocs(Array.from(new Set<Doc>(this.props.links)), this.props.View.props.docFilters(), []);
+ }
- const link = <img
- style={{ width: "22px", height: "16px" }}
- id={"link-icon"}
- src={`/assets/${"link.png"}`} />;
+ @computed get linkButtonInner() {
+ const btnDim = this.props.InMenu ? "20px" : "30px";
+ const link = <img style={{ width: "22px", height: "16px" }} src={`/assets/${"link.png"}`} />;
- const linkButton = <div className="documentLinksButton-cont" ref={this._linkButton} style={{
- left: this.props.Offset?.[0], top: this.props.Offset?.[1], right: this.props.Offset?.[2], bottom: this.props.Offset?.[3]
- }}>
- <div className={"documentLinksButton"} style={{
- backgroundColor: this.props.InMenu ? "" : "#add8e6",
- color: this.props.InMenu ? "white" : "black",
- width: this.props.InMenu ? "20px" : "30px",
- height: this.props.InMenu ? "20px" : "30px",
- }}
+ return <div className="documentLinksButton-cont" ref={this._linkButton}
+ style={{ left: this.props.Offset?.[0], top: this.props.Offset?.[1], right: this.props.Offset?.[2], bottom: this.props.Offset?.[3] }}
+ >
+ <div className={"documentLinksButton"}
onPointerDown={this.onLinkButtonDown} onClick={this.onLinkClick}
- // onPointerLeave={action(() => LinkDocPreview.LinkInfo = undefined)}
- // onPointerEnter={action(e => links.length && (LinkDocPreview.LinkInfo = {
- // addDocTab: this.props.View.props.addDocTab,
- // linkSrc: this.props.View.props.Document,
- // linkDoc: links[0],
- // Location: [e.clientX, e.clientY + 20]
- // }))}
- >
-
- {/* {this.props.InMenu ? this.props.StartLink ? <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" /> :
- <FontAwesomeIcon className="documentdecorations-icon" icon="hand-paper" size="sm" /> : links.length} */}
-
- {this.props.InMenu ? this.props.StartLink ? <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" /> :
- link : Array.from(links).length}
-
+ style={{
+ backgroundColor: this.props.InMenu ? "" : "#add8e6",
+ color: this.props.InMenu ? "white" : "black",
+ width: btnDim,
+ height: btnDim,
+ }} >
+ {this.props.InMenu ?
+ this.props.StartLink ?
+ <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" />
+ : link
+ : Array.from(this.filteredLinks).length}
</div>
{this.props.InMenu && !this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document ?
<div className={"documentLinksButton-endLink"}
style={{
- width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px",
+ width: btnDim, height: btnDim,
backgroundColor: DocumentLinksButton.StartLink ? "" : "grey",
opacity: DocumentLinksButton.StartLink ? "" : "50%",
border: DocumentLinksButton.StartLink ? "" : "none",
cursor: DocumentLinksButton.StartLink ? "pointer" : "default"
}}
- onPointerDown={DocumentLinksButton.StartLink ? this.completeLink : emptyFunction}
- onClick={e => DocumentLinksButton.StartLink ? DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this.props.View.props.Document, true, this.props.View) : emptyFunction} /> : (null)
+ onPointerDown={DocumentLinksButton.StartLink && this.completeLink}
+ onClick={e => DocumentLinksButton.StartLink && DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this.props.View.props.Document, true, this.props.View)} />
+ : (null)
}
- {
- DocumentLinksButton.StartLink === this.props.View.props.Document && this.props.InMenu && this.props.StartLink ? <div className={"documentLinksButton-startLink"}
- style={{ width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px" }}
- onPointerDown={this.clearLinks} onClick={this.clearLinks}
- /> : (null)
+ {DocumentLinksButton.StartLink === this.props.View.props.Document && this.props.InMenu && this.props.StartLink ?
+ <div className={"documentLinksButton-startLink"} onPointerDown={this.clearLinks} onClick={this.clearLinks} style={{ width: btnDim, height: btnDim }} />
+ : (null)
}
</div >;
+ }
+
+ @computed get linkButton() {
+ TraceMobx();
+
+ const menuTitle = this.props.StartLink ? "Drag or tap to start link" : "Tap to complete link";
+ const buttonTitle = "Tap to view links";
+ const title = this.props.InMenu ? menuTitle : buttonTitle;
- return (!Array.from(links).length) && !this.props.AlwaysOn ? (null) :
+ return !Array.from(this.filteredLinks).length && !this.props.AlwaysOn ? (null) :
this.props.InMenu && (DocumentLinksButton.StartLink || this.props.StartLink) ?
<Tooltip title={<><div className="dash-tooltip">{title}</div></>}>
- {linkButton}
- </Tooltip> : !!!DocumentLinksButton.EditLink && !this.props.InMenu ?
+ {this.linkButtonInner}
+ </Tooltip>
+ :
+ !DocumentLinksButton.EditLink && !this.props.InMenu ?
<Tooltip title={<><div className="dash-tooltip">{title}</div></>}>
- {linkButton}
- </Tooltip> :
- linkButton;
+ {this.linkButtonInner}
+ </Tooltip>
+ : this.linkButtonInner;
}
render() {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index f6a147c50..3ebaad0a3 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -990,7 +990,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
anchorPanelHeight = () => this.props.PanelHeight() || 1;
@computed get directLinks() { TraceMobx(); return LinkManager.Instance.getAllDirectLinks(this.rootDoc); }
- @computed get allLinks() { TraceMobx(); return DocListCast(this.Document.links); }
+ @computed get allLinks() { TraceMobx(); return LinkManager.Instance.getAllRelatedLinks(this.rootDoc); }
@computed get allAnchors() {
TraceMobx();
if (this.props.LayoutTemplateString?.includes("LinkAnchorBox")) return null;