aboutsummaryrefslogtreecommitdiff
path: root/src/client/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/util')
-rw-r--r--src/client/util/DocumentManager.ts26
-rw-r--r--src/client/util/DragManager.ts14
-rw-r--r--src/client/util/LinkManager.ts137
3 files changed, 153 insertions, 24 deletions
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index ff0c1560b..fc78993b8 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -9,6 +9,7 @@ import { CollectionView } from '../views/collections/CollectionView';
import { CollectionPDFView } from '../views/collections/CollectionPDFView';
import { CollectionVideoView } from '../views/collections/CollectionVideoView';
import { Id } from '../../new_fields/FieldSymbols';
+import { LinkManager } from './LinkManager';
export class DocumentManager {
@@ -83,35 +84,24 @@ export class DocumentManager {
@computed
public get LinkedDocumentViews() {
- return DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false)).reduce((pairs, dv) => {
- let linksList = DocListCast(dv.props.Document.linkedToDocs);
+ let linked = DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false)).reduce((pairs, dv) => {
+
+ let linksList = LinkManager.Instance.findAllRelatedLinks(dv.props.Document);
if (linksList && linksList.length) {
pairs.push(...linksList.reduce((pairs, link) => {
if (link) {
- let linkToDoc = FieldValue(Cast(link.linkedTo, Doc));
- if (linkToDoc) {
- DocumentManager.Instance.getDocumentViews(linkToDoc).map(docView1 =>
+ let destination = LinkManager.Instance.findOppositeAnchor(link, dv.props.Document);
+ if (destination) {
+ DocumentManager.Instance.getDocumentViews(destination).map(docView1 =>
pairs.push({ a: dv, b: docView1, l: link }));
}
}
return pairs;
}, [] as { a: DocumentView, b: DocumentView, l: Doc }[]));
}
- linksList = DocListCast(dv.props.Document.linkedFromDocs);
- if (linksList && linksList.length) {
- pairs.push(...linksList.reduce((pairs, link) => {
- if (link) {
- let linkFromDoc = FieldValue(Cast(link.linkedFrom, Doc));
- if (linkFromDoc) {
- DocumentManager.Instance.getDocumentViews(linkFromDoc).map(docView1 =>
- pairs.push({ a: dv, b: docView1, l: link }));
- }
- }
- return pairs;
- }, pairs));
- }
return pairs;
}, [] as { a: DocumentView, b: DocumentView, l: Doc }[]);
+ return linked;
}
@undoBatch
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index ab00fabe1..b32c25b0a 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -4,6 +4,7 @@ import { Cast } from "../../new_fields/Types";
import { emptyFunction } from "../../Utils";
import { CollectionDockingView } from "../views/collections/CollectionDockingView";
import * as globalCssVariables from "../views/globalCssVariables.scss";
+import { LinkManager } from "./LinkManager";
import { URLField } from "../../new_fields/URLField";
import { SelectionManager } from "./SelectionManager";
@@ -45,14 +46,15 @@ export function SetupDrag(_reference: React.RefObject<HTMLElement>, docFunc: ()
export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: number, sourceDoc: Doc) {
let srcTarg = sourceDoc.proto;
let draggedDocs: Doc[] = [];
- let draggedFromDocs: Doc[] = [];
if (srcTarg) {
- let linkToDocs = await DocListCastAsync(srcTarg.linkedToDocs);
- let linkFromDocs = await DocListCastAsync(srcTarg.linkedFromDocs);
- if (linkToDocs) draggedDocs = linkToDocs.map(linkDoc => Cast(linkDoc.linkedTo, Doc) as Doc);
- if (linkFromDocs) draggedFromDocs = linkFromDocs.map(linkDoc => Cast(linkDoc.linkedFrom, Doc) as Doc);
+ let linkDocs = LinkManager.Instance.findAllRelatedLinks(srcTarg);
+ if (linkDocs) {
+ draggedDocs = linkDocs.map(link => {
+ return LinkManager.Instance.findOppositeAnchor(link, sourceDoc);
+ });
+ }
}
- draggedDocs.push(...draggedFromDocs);
+ // draggedDocs.push(...draggedFromDocs);
if (draggedDocs.length) {
let moddrag: Doc[] = [];
for (const draggedDoc of draggedDocs) {
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
new file mode 100644
index 000000000..23ba9d2e4
--- /dev/null
+++ b/src/client/util/LinkManager.ts
@@ -0,0 +1,137 @@
+import { observable } from "mobx";
+import { StrCast, Cast } from "../../new_fields/Types";
+import { Doc, DocListCast } from "../../new_fields/Doc";
+import { listSpec } from "../../new_fields/Schema";
+import { List } from "../../new_fields/List";
+
+
+/*
+ * link doc:
+ * - anchor1: doc
+ * - anchor1page: number
+ * - anchor1groups: list of group docs representing the groups anchor1 categorizes this link/anchor2 in
+ * - anchor2: doc
+ * - anchor2page: number
+ * - anchor2groups: list of group docs representing the groups anchor2 categorizes this link/anchor1 in
+ *
+ * group doc:
+ * - type: string representing the group type/name/category
+ * - metadata: doc representing the metadata kvps
+ *
+ * metadata doc:
+ * - user defined kvps
+ */
+export class LinkManager {
+ private static _instance: LinkManager;
+ public static get Instance(): LinkManager {
+ return this._instance || (this._instance = new this());
+ }
+ private constructor() {
+ }
+
+ @observable public allLinks: Array<Doc> = []; // list of link docs
+ @observable public groupMetadataKeys: Map<string, Array<string>> = new Map();
+ // map of group type to list of its metadata keys; serves as a dictionary of groups to what kind of metadata it hodls
+
+ // finds all links that contain the given anchor
+ public findAllRelatedLinks(anchor: Doc): Array<Doc> {
+ return LinkManager.Instance.allLinks.filter(
+ link => Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, new Doc)) || Doc.AreProtosEqual(anchor, Cast(link.anchor2, Doc, new Doc)));
+ }
+
+ // returns map of group type to anchor's links in that group type
+ public findRelatedGroupedLinks(anchor: Doc): Map<string, Array<Doc>> {
+ let related = this.findAllRelatedLinks(anchor);
+ let anchorGroups = new Map<string, Array<Doc>>();
+ related.forEach(link => {
+ let groups = LinkManager.Instance.getAnchorGroups(link, anchor);
+
+ if (groups.length > 0) {
+ groups.forEach(groupDoc => {
+ let groupType = StrCast(groupDoc.type);
+ let group = anchorGroups.get(groupType);
+ if (group) group.push(link);
+ else group = [link];
+ anchorGroups.set(groupType, group);
+ });
+ } else {
+ // if link is in no groups then put it in default group
+ let group = anchorGroups.get("*");
+ if (group) group.push(link);
+ else group = [link];
+ anchorGroups.set("*", group);
+ }
+
+ });
+ return anchorGroups;
+ }
+
+ // returns a list of all metadata docs associated with the given group type
+ public findAllMetadataDocsInGroup(groupType: string): Array<Doc> {
+ let md: Doc[] = [];
+ let allLinks = LinkManager.Instance.allLinks;
+ allLinks.forEach(linkDoc => {
+ let anchor1Groups = LinkManager.Instance.getAnchorGroups(linkDoc, Cast(linkDoc.anchor1, Doc, new Doc));
+ let anchor2Groups = LinkManager.Instance.getAnchorGroups(linkDoc, Cast(linkDoc.anchor2, Doc, new Doc));
+ anchor1Groups.forEach(groupDoc => { if (StrCast(groupDoc.type).toUpperCase() === groupType.toUpperCase()) md.push(Cast(groupDoc.metadata, Doc, new Doc)); });
+ anchor2Groups.forEach(groupDoc => { if (StrCast(groupDoc.type).toUpperCase() === groupType.toUpperCase()) md.push(Cast(groupDoc.metadata, Doc, new Doc)); });
+ });
+ return md;
+ }
+
+ // removes all group docs from all links with the given group type
+ public deleteGroup(groupType: string): void {
+ let deleted = LinkManager.Instance.groupMetadataKeys.delete(groupType);
+ if (deleted) {
+ LinkManager.Instance.allLinks.forEach(linkDoc => {
+ LinkManager.Instance.removeGroupFromAnchor(linkDoc, Cast(linkDoc.anchor1, Doc, new Doc), groupType);
+ LinkManager.Instance.removeGroupFromAnchor(linkDoc, Cast(linkDoc.anchor2, Doc, new Doc), groupType);
+ });
+ }
+ }
+
+ // removes group doc of given group type only from given anchor on given link
+ public removeGroupFromAnchor(linkDoc: Doc, anchor: Doc, groupType: string) {
+ let groups = LinkManager.Instance.getAnchorGroups(linkDoc, anchor);
+ let newGroups = groups.filter(groupDoc => StrCast(groupDoc.type).toUpperCase() !== groupType.toUpperCase());
+ LinkManager.Instance.setAnchorGroups(linkDoc, anchor, newGroups);
+ }
+
+ // checks if a link with the given anchors exists
+ public doesLinkExist(anchor1: Doc, anchor2: Doc) {
+ let allLinks = LinkManager.Instance.allLinks;
+ let index = allLinks.findIndex(linkDoc => {
+ return (Doc.AreProtosEqual(Cast(linkDoc.anchor1, Doc, new Doc), anchor1) && Doc.AreProtosEqual(Cast(linkDoc.anchor2, Doc, new Doc), anchor2)) ||
+ (Doc.AreProtosEqual(Cast(linkDoc.anchor1, Doc, new Doc), anchor2) && Doc.AreProtosEqual(Cast(linkDoc.anchor2, Doc, new Doc), anchor1));
+ });
+ return index !== -1;
+ }
+
+ // finds the opposite anchor of a given anchor in a link
+ public findOppositeAnchor(linkDoc: Doc, anchor: Doc): Doc {
+ if (Doc.AreProtosEqual(anchor, Cast(linkDoc.anchor1, Doc, new Doc))) {
+ return Cast(linkDoc.anchor2, Doc, new Doc);
+ } else {
+ return Cast(linkDoc.anchor1, Doc, new Doc);
+ }
+ }
+
+ // gets the groups associates with an anchor in a link
+ public getAnchorGroups(linkDoc: Doc, anchor: Doc): Array<Doc> {
+ if (Doc.AreProtosEqual(anchor, Cast(linkDoc.anchor1, Doc, new Doc))) {
+ return DocListCast(linkDoc.anchor1Groups);
+ } else {
+ return DocListCast(linkDoc.anchor2Groups);
+ }
+ }
+
+ // sets the groups of the given anchor in the given link
+ public setAnchorGroups(linkDoc: Doc, anchor: Doc, groups: Doc[]) {
+ if (Doc.AreProtosEqual(anchor, Cast(linkDoc.anchor1, Doc, new Doc))) {
+ linkDoc.anchor1Groups = new List<Doc>(groups);
+ } else {
+ linkDoc.anchor2Groups = new List<Doc>(groups);
+ }
+ }
+
+} \ No newline at end of file