aboutsummaryrefslogtreecommitdiff
path: root/src/client/views
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views')
-rw-r--r--src/client/views/DocumentDecorations.tsx2
-rw-r--r--src/client/views/MainView.tsx7
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx4
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx18
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx7
-rw-r--r--src/client/views/nodes/DocumentView.tsx8
-rw-r--r--src/client/views/nodes/LinkButtonBox.scss34
-rw-r--r--src/client/views/nodes/LinkButtonBox.tsx126
-rw-r--r--src/client/views/nodes/LinkEditor.tsx323
-rw-r--r--src/client/views/nodes/LinkMenu.tsx2
-rw-r--r--src/client/views/nodes/LinkMenuGroup.tsx8
-rw-r--r--src/client/views/nodes/LinkMenuItem.tsx6
12 files changed, 254 insertions, 291 deletions
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 926273633..3a2752d7e 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -573,7 +573,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
let linkButton = null;
if (SelectionManager.SelectedDocuments().length > 0) {
let selFirst = SelectionManager.SelectedDocuments()[0];
- let linkCount = LinkManager.Instance.findAllRelatedLinks(selFirst.props.Document).length;
+ let linkCount = LinkManager.Instance.getAllRelatedLinks(selFirst.props.Document).length;
linkButton = (<Flyout
anchorPoint={anchorPoints.RIGHT_TOP}
content={<LinkMenu docView={selFirst}
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 51630c29b..d90e9d23e 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -35,6 +35,8 @@ import { HistoryUtil } from '../util/History';
import { CollectionBaseView } from './collections/CollectionBaseView';
import PDFMenu from './pdf/PDFMenu';
import { InkTool } from '../../new_fields/InkField';
+import { LinkManager } from '../util/LinkManager';
+import { List } from '../../new_fields/List';
@observer
@@ -146,6 +148,11 @@ export class MainView extends React.Component {
let freeformDoc = Docs.FreeformDocument([], { x: 0, y: 400, width: this.pwidth * .7, height: this.pheight, title: `WS collection ${list.length + 1}` });
var dockingLayout = { content: [{ type: 'row', content: [CollectionDockingView.makeDocumentConfig(CurrentUserUtils.UserDocument, 150), CollectionDockingView.makeDocumentConfig(freeformDoc, 600)] }] };
let mainDoc = Docs.DockDocument([CurrentUserUtils.UserDocument, freeformDoc], JSON.stringify(dockingLayout), { title: `Workspace ${list.length + 1}` }, id);
+ if (!CurrentUserUtils.UserDocument.linkManagerDoc) {
+ let linkManagerDoc = new Doc();
+ linkManagerDoc.allLinks = new List<Doc>([]);
+ CurrentUserUtils.UserDocument.linkManagerDoc = linkManagerDoc;
+ }
list.push(mainDoc);
// bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
setTimeout(() => {
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index c82027da5..4140f8029 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -354,9 +354,9 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
tab.reactComponents = [upDiv];
tab.element.append(upDiv);
counter.DashDocId = tab.contentItem.config.props.documentId;
- tab.reactionDisposer = reaction(() => [LinkManager.Instance.findAllRelatedLinks(doc), doc.title],
+ tab.reactionDisposer = reaction(() => [LinkManager.Instance.getAllRelatedLinks(doc), doc.title],
() => {
- counter.innerHTML = LinkManager.Instance.findAllRelatedLinks(doc).length;
+ counter.innerHTML = LinkManager.Instance.getAllRelatedLinks(doc).length;
tab.titleElement[0].textContent = doc.title;
}, { fireImmediately: true });
tab.titleElement[0].DashDocId = tab.contentItem.config.props.documentId;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 0b922b3c4..7bc3ad124 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -73,7 +73,7 @@ class TreeView extends React.Component<TreeViewProps> {
@undoBatch delete = () => this.props.deleteDoc(this.props.document);
@undoBatch openRight = async () => this.props.addDocTab(this.props.document, "openRight");
- onPointerDown = (e: React.PointerEvent) => e.stopPropagation()
+ onPointerDown = (e: React.PointerEvent) => e.stopPropagation();
onPointerEnter = (e: React.PointerEvent): void => {
this.props.active() && (this.props.document.libraryBrush = true);
if (e.buttons === 1 && SelectionManager.GetIsDragging()) {
@@ -115,7 +115,7 @@ class TreeView extends React.Component<TreeViewProps> {
return this.props.document !== target && this.props.deleteDoc(doc) && addDoc(doc);
}
@action
- indent = () => this.props.addDocument(this.props.document) && this.delete();
+ indent = () => this.props.addDocument(this.props.document) && this.delete()
renderBullet() {
let docList = Cast(this.props.document["data"], listSpec(Doc));
@@ -167,7 +167,7 @@ class TreeView extends React.Component<TreeViewProps> {
keyList.push(key);
}
});
- if (LinkManager.Instance.findAllRelatedLinks(this.props.document).length > 0) keyList.push("links");
+ if (LinkManager.Instance.getAllRelatedLinks(this.props.document).length > 0) keyList.push("links");
if (keyList.indexOf("data") !== -1) {
keyList.splice(keyList.indexOf("data"), 1);
}
@@ -281,9 +281,9 @@ class TreeView extends React.Component<TreeViewProps> {
let ele: JSX.Element[] = [];
let remDoc = (doc: Doc) => this.remove(doc, this._chosenKey);
let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => TreeView.AddDocToList(this.props.document, this._chosenKey, doc, addBefore, before);
- let groups = LinkManager.Instance.findRelatedGroupedLinks(this.props.document);
+ let groups = LinkManager.Instance.getRelatedGroupedLinks(this.props.document);
groups.forEach((groupLinkDocs, groupType) => {
- let destLinks = groupLinkDocs.map(d => LinkManager.Instance.findOppositeAnchor(d, this.props.document));
+ let destLinks = groupLinkDocs.map(d => LinkManager.Instance.getOppositeAnchor(d, this.props.document));
ele.push(
<div key={"treeviewlink-" + groupType + "subtitle"}>
<div className="collectionTreeView-subtitle">{groupType}:</div>
@@ -325,7 +325,7 @@ class TreeView extends React.Component<TreeViewProps> {
addDocTab={this.props.addDocTab}
setPreviewScript={emptyFunction}>
</CollectionSchemaPreview>
- </div>
+ </div>;
}
}
return <div className="treeViewItem-container" ref={this.createTreeDropTarget} onContextMenu={this.onWorkspaceContextMenu}>
@@ -364,14 +364,14 @@ class TreeView extends React.Component<TreeViewProps> {
TreeView.AddDocToList(docList[i - 1], fieldKey, child);
remove(child);
}
- }
+ };
let addDocument = (doc: Doc, relativeTo?: Doc, before?: boolean) => {
return add(doc, relativeTo ? relativeTo : docList[i], before !== undefined ? before : false);
- }
+ };
let rowHeight = () => {
let aspect = NumCast(child.nativeWidth, 0) / NumCast(child.nativeHeight, 0);
return aspect ? Math.min(child[WidthSym](), rowWidth()) / aspect : child[HeightSym]();
- }
+ };
return <TreeView
document={child}
treeViewId={treeViewId}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index 76e089f08..bb8e8a5c2 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -98,17 +98,17 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
// console.log("CONNECTION", StrCast(d.a.props.Document.title), StrCast(d.b.props.Document.title));
// });
- console.log("CONNECTIONS");
+ // console.log("CONNECTIONS");
let connections = DocumentManager.Instance.LinkedDocumentViews.reduce((drawnPairs, connection) => {
let srcViews = this.documentAnchors(connection.a);
let targetViews = this.documentAnchors(connection.b);
- console.log(srcViews.length, targetViews.length);
+ // console.log(srcViews.length, targetViews.length);
let possiblePairs: { a: Doc, b: Doc, }[] = [];
srcViews.map(sv => {
targetViews.map(tv => {
- console.log("PUSH", StrCast(sv.props.Document.title), StrCast(sv.props.Document.id), StrCast(tv.props.Document.title), StrCast(tv.props.Document.id));
+ // console.log("PUSH", StrCast(sv.props.Document.title), StrCast(sv.props.Document.id), StrCast(tv.props.Document.title), StrCast(tv.props.Document.id));
possiblePairs.push({ a: sv.props.Document, b: tv.props.Document });
});
});
@@ -142,7 +142,6 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
}
render() {
- console.log("\n");
return (
<div className="collectionfreeformlinksview-container">
<svg className="collectionfreeformlinksview-svgCanvas">
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 1fc2cf770..7b185336b 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -285,7 +285,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
let subBulletDocs = await DocListCastAsync(this.props.Document.subBulletDocs);
let maximizedDocs = await DocListCastAsync(this.props.Document.maximizedDocs);
let summarizedDocs = await DocListCastAsync(this.props.Document.summarizedDocs);
- let linkedDocs = LinkManager.Instance.findAllRelatedLinks(this.props.Document);
+ let linkedDocs = LinkManager.Instance.getAllRelatedLinks(this.props.Document);
let expandedDocs: Doc[] = [];
expandedDocs = subBulletDocs ? [...subBulletDocs, ...expandedDocs] : expandedDocs;
expandedDocs = maximizedDocs ? [...maximizedDocs, ...expandedDocs] : expandedDocs;
@@ -536,11 +536,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
onPointerEnter = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = true; };
onPointerLeave = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = false; };
- onDragOver = (e: React.DragEvent): void => {
- this.props.Document.libraryBrush = true;
- console.log("dragOver");
- };
- onDragLeave = (e: React.DragEvent): void => { this.props.Document.libraryBrush = false; };
isSelected = () => SelectionManager.IsSelected(this);
@action select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); };
@@ -585,7 +580,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
// display: display ? "block" : "none"
}}
onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick}
- onDragOver={this.onDragOver} onDragLeave={this.onDragLeave}
onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}
>
{this.contents}
diff --git a/src/client/views/nodes/LinkButtonBox.scss b/src/client/views/nodes/LinkButtonBox.scss
index 24bfd2c9f..6be2dcf60 100644
--- a/src/client/views/nodes/LinkButtonBox.scss
+++ b/src/client/views/nodes/LinkButtonBox.scss
@@ -1,18 +1,18 @@
-.linkBox-cont {
- width: 200px;
- height: 100px;
- background-color: black;
- text-align: center;
- color: white;
- padding: 10px;
- border-radius: 5px;
- position: relative;
+// .linkBox-cont {
+// width: 200px;
+// height: 100px;
+// background-color: black;
+// text-align: center;
+// color: white;
+// padding: 10px;
+// border-radius: 5px;
+// position: relative;
- .linkBox-cont-wrapper {
- width: calc(100% - 20px);
- position: absolute;
- left: 50%;
- top: 50%;
- transform: translate(-50%, -50%);
- }
-} \ No newline at end of file
+// .linkBox-cont-wrapper {
+// width: calc(100% - 20px);
+// position: absolute;
+// left: 50%;
+// top: 50%;
+// transform: translate(-50%, -50%);
+// }
+// } \ No newline at end of file
diff --git a/src/client/views/nodes/LinkButtonBox.tsx b/src/client/views/nodes/LinkButtonBox.tsx
index 8a7c1ed8b..440847ead 100644
--- a/src/client/views/nodes/LinkButtonBox.tsx
+++ b/src/client/views/nodes/LinkButtonBox.tsx
@@ -1,63 +1,63 @@
-import React = require("react");
-import { library } from '@fortawesome/fontawesome-svg-core';
-import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote } from '@fortawesome/free-solid-svg-icons';
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { computed, observable, runInAction } from "mobx";
-import { observer } from "mobx-react";
-import { FieldView, FieldViewProps } from './FieldView';
-import "./LinkButtonBox.scss";
-import { DocumentView } from "./DocumentView";
-import { Doc } from "../../../new_fields/Doc";
-import { LinkButtonField } from "../../../new_fields/LinkButtonField";
-import { Cast, StrCast, BoolCast } from "../../../new_fields/Types";
-import { CollectionDockingView } from "../collections/CollectionDockingView";
-import { DocumentManager } from "../../util/DocumentManager";
-import { Id } from "../../../new_fields/FieldSymbols";
-
-library.add(faCaretUp);
-library.add(faObjectGroup);
-library.add(faStickyNote);
-library.add(faFilePdf);
-library.add(faFilm);
-
-@observer
-export class LinkButtonBox extends React.Component<FieldViewProps> {
- public static LayoutString() { return FieldView.LayoutString(LinkButtonBox); }
-
- followLink = (): void => {
- console.log("follow link???");
- let field = Cast(this.props.Document[this.props.fieldKey], LinkButtonField, new LinkButtonField({ sourceViewId: "-1", targetViewId: "-1" }));
- let targetView = DocumentManager.Instance.getDocumentViewById(field.data.targetViewId);
- if (targetView && targetView.props.ContainingCollectionView) {
- CollectionDockingView.Instance.AddRightSplit(targetView.props.ContainingCollectionView.props.Document);
- }
- }
-
- render() {
-
- let field = Cast(this.props.Document[this.props.fieldKey], LinkButtonField, new LinkButtonField({ sourceViewId: "-1", targetViewId: "-1" }));
- let targetView = DocumentManager.Instance.getDocumentViewById(field.data.targetViewId);
-
- let text = "Could not find link";
- if (targetView) {
- let context = targetView.props.ContainingCollectionView ? (" in the context of " + StrCast(targetView.props.ContainingCollectionView.props.Document.title)) : "";
- text = "Link to " + StrCast(targetView.props.Document.title) + context;
- }
-
- let activeDvs = DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false));
- let display = activeDvs.reduce((found, dv) => {
- let matchSv = field.data.sourceViewId === StrCast(dv.props.Document[Id]);
- let matchTv = field.data.targetViewId === StrCast(dv.props.Document[Id]);
- let match = matchSv || matchTv;
- return match || found;
- }, false);
-
- return (
- <div className="linkBox-cont" style={{ display: display ? "block" : "none" }}>
- <div className="linkBox-cont-wrapper">
- <p>{text}</p>
- </div>
- </div >
- );
- }
-} \ No newline at end of file
+// import React = require("react");
+// import { library } from '@fortawesome/fontawesome-svg-core';
+// import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote } from '@fortawesome/free-solid-svg-icons';
+// import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+// import { computed, observable, runInAction } from "mobx";
+// import { observer } from "mobx-react";
+// import { FieldView, FieldViewProps } from './FieldView';
+// import "./LinkButtonBox.scss";
+// import { DocumentView } from "./DocumentView";
+// import { Doc } from "../../../new_fields/Doc";
+// import { LinkButtonField } from "../../../new_fields/LinkButtonField";
+// import { Cast, StrCast, BoolCast } from "../../../new_fields/Types";
+// import { CollectionDockingView } from "../collections/CollectionDockingView";
+// import { DocumentManager } from "../../util/DocumentManager";
+// import { Id } from "../../../new_fields/FieldSymbols";
+
+// library.add(faCaretUp);
+// library.add(faObjectGroup);
+// library.add(faStickyNote);
+// library.add(faFilePdf);
+// library.add(faFilm);
+
+// @observer
+// export class LinkButtonBox extends React.Component<FieldViewProps> {
+// public static LayoutString() { return FieldView.LayoutString(LinkButtonBox); }
+
+// followLink = (): void => {
+// console.log("follow link???");
+// let field = Cast(this.props.Document[this.props.fieldKey], LinkButtonField, new LinkButtonField({ sourceViewId: "-1", targetViewId: "-1" }));
+// let targetView = DocumentManager.Instance.getDocumentViewById(field.data.targetViewId);
+// if (targetView && targetView.props.ContainingCollectionView) {
+// CollectionDockingView.Instance.AddRightSplit(targetView.props.ContainingCollectionView.props.Document);
+// }
+// }
+
+// render() {
+
+// let field = Cast(this.props.Document[this.props.fieldKey], LinkButtonField, new LinkButtonField({ sourceViewId: "-1", targetViewId: "-1" }));
+// let targetView = DocumentManager.Instance.getDocumentViewById(field.data.targetViewId);
+
+// let text = "Could not find link";
+// if (targetView) {
+// let context = targetView.props.ContainingCollectionView ? (" in the context of " + StrCast(targetView.props.ContainingCollectionView.props.Document.title)) : "";
+// text = "Link to " + StrCast(targetView.props.Document.title) + context;
+// }
+
+// let activeDvs = DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false));
+// let display = activeDvs.reduce((found, dv) => {
+// let matchSv = field.data.sourceViewId === StrCast(dv.props.Document[Id]);
+// let matchTv = field.data.targetViewId === StrCast(dv.props.Document[Id]);
+// let match = matchSv || matchTv;
+// return match || found;
+// }, false);
+
+// return (
+// <div className="linkBox-cont" style={{ display: display ? "block" : "none" }}>
+// <div className="linkBox-cont-wrapper">
+// <p>{text}</p>
+// </div>
+// </div >
+// );
+// }
+// } \ No newline at end of file
diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx
index 95199bae2..5f4f7d4f0 100644
--- a/src/client/views/nodes/LinkEditor.tsx
+++ b/src/client/views/nodes/LinkEditor.tsx
@@ -17,9 +17,8 @@ library.add(faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, fa
interface GroupTypesDropdownProps {
- groupId: string;
groupType: string;
- setGroup: (groupId: string, group: string) => void;
+ setGroupType: (group: string) => void;
}
// this dropdown could be generalized
@observer
@@ -32,20 +31,20 @@ class GroupTypesDropdown extends React.Component<GroupTypesDropdownProps> {
@action
createGroup = (groupType: string): void => {
- this.props.setGroup(this.props.groupId, groupType);
- LinkManager.Instance.groupMetadataKeys.set(groupType, []);
+ this.props.setGroupType(groupType);
+ LinkManager.Instance.addGroupType(groupType);
}
renderOptions = (): JSX.Element[] | JSX.Element => {
if (this._searchTerm === "") return <></>;
- let allGroupTypes = Array.from(LinkManager.Instance.groupMetadataKeys.keys());
+ let allGroupTypes = Array.from(LinkManager.Instance.getAllGroupTypes());
let groupOptions = allGroupTypes.filter(groupType => groupType.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1);
let exactFound = groupOptions.findIndex(groupType => groupType.toUpperCase() === this._searchTerm.toUpperCase()) > -1;
let options = groupOptions.map(groupType => {
return <div key={groupType} className="linkEditor-option"
- onClick={() => { this.props.setGroup(this.props.groupId, groupType); this.setGroupType(groupType); this.setSearchTerm(""); }}>{groupType}</div>;
+ onClick={() => { this.props.setGroupType(groupType); this.setGroupType(groupType); this.setSearchTerm(""); }}>{groupType}</div>;
});
// if search term does not already exist as a group type, give option to create new group type
@@ -85,7 +84,7 @@ class LinkMetadataEditor extends React.Component<LinkMetadataEditorProps> {
@action
setMetadataKey = (value: string): void => {
- let groupMdKeys = new Array(...LinkManager.Instance.groupMetadataKeys.get(this.props.groupType)!);
+ let groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);
// don't allow user to create existing key
let newIndex = groupMdKeys.findIndex(key => key.toUpperCase() === value.toUpperCase());
@@ -98,12 +97,15 @@ class LinkMetadataEditor extends React.Component<LinkMetadataEditorProps> {
}
// set new value for key
- let currIndex = groupMdKeys.findIndex(key => key.toUpperCase() === this._key.toUpperCase());
+ let currIndex = groupMdKeys.findIndex(key => {
+ console.log("finding index this", key.toUpperCase(), "that", this._key.toUpperCase());
+ return StrCast(key).toUpperCase() === this._key.toUpperCase();
+ });
if (currIndex === -1) console.error("LinkMetadataEditor: key was not found");
groupMdKeys[currIndex] = value;
this._key = value;
- LinkManager.Instance.groupMetadataKeys.set(this.props.groupType, groupMdKeys);
+ LinkManager.Instance.setMetadataKeysForGroup(this.props.groupType, groupMdKeys);
}
@action
@@ -116,13 +118,13 @@ class LinkMetadataEditor extends React.Component<LinkMetadataEditorProps> {
@action
removeMetadata = (): void => {
- let groupMdKeys = new Array(...LinkManager.Instance.groupMetadataKeys.get(this.props.groupType)!);
+ let groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);
let index = groupMdKeys.findIndex(key => key.toUpperCase() === this._key.toUpperCase());
if (index === -1) console.error("LinkMetadataEditor: key was not found");
groupMdKeys.splice(index, 1);
- LinkManager.Instance.groupMetadataKeys.set(this.props.groupType, groupMdKeys);
+ LinkManager.Instance.setMetadataKeysForGroup(this.props.groupType, groupMdKeys);
this._key = "";
}
@@ -137,215 +139,176 @@ class LinkMetadataEditor extends React.Component<LinkMetadataEditorProps> {
}
}
-
-interface LinkEditorProps {
+interface LinkGroupEditorProps {
sourceDoc: Doc;
linkDoc: Doc;
- showLinks: () => void;
+ groupDoc: Doc;
}
@observer
-export class LinkEditor extends React.Component<LinkEditorProps> {
+export class LinkGroupEditor extends React.Component<LinkGroupEditorProps> {
- // map of temporary group id to the corresponding group doc
- @observable private _groups: Map<string, Doc> = new Map();
-
- constructor(props: LinkEditorProps) {
- super(props);
+ @action
+ setGroupType = (groupType: string): void => {
+ console.log("SET GROUP TYPE TO", groupType);
+ this.props.groupDoc.type = groupType;
+ console.log("GROUP TYPE HAS BEEN SET TO ", StrCast(this.props.groupDoc.type));
+ }
- let groups = new Map<string, Doc>();
- let groupList = LinkManager.Instance.getAnchorGroups(props.linkDoc, props.sourceDoc);
- groupList.forEach(groupDoc => {
- let id = Utils.GenerateGuid();
- groups.set(id, groupDoc);
- });
- this._groups = groups;
+ removeGroupFromLink = (groupType: string): void => {
+ LinkManager.Instance.removeGroupFromAnchor(this.props.linkDoc, this.props.sourceDoc, groupType);
}
- @action
- deleteLink = (): void => {
- let index = LinkManager.Instance.allLinks.indexOf(this.props.linkDoc);
- LinkManager.Instance.allLinks.splice(index, 1);
- this.props.showLinks();
+ deleteGroup = (groupType: string): void => {
+ LinkManager.Instance.deleteGroupType(groupType);
}
- @action
- addGroup = (): void => {
- // new group only gets added if there is not already a group with type "new group"
- let index = Array.from(this._groups.values()).findIndex(groupDoc => {
- return groupDoc.type === "New Group";
- });
- if (index > -1) return;
+ copyGroup = (groupType: string): void => {
+ let sourceGroupDoc = this.props.groupDoc;
+ let sourceMdDoc = Cast(sourceGroupDoc.metadata, Doc, new Doc);
- // create new metadata document for group
- let mdDoc = Docs.TextDocument();
- mdDoc.proto!.anchor1 = this.props.sourceDoc.title;
- mdDoc.proto!.anchor2 = LinkManager.Instance.findOppositeAnchor(this.props.linkDoc, this.props.sourceDoc).title;
+ let destDoc = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc);
+ // let destGroupList = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, destDoc);
+ let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType);
- // create new group document
- let groupDoc = Docs.TextDocument();
- groupDoc.proto!.type = "New Group";
- groupDoc.proto!.metadata = mdDoc;
+ // create new metadata doc with copied kvp
+ let destMdDoc = new Doc();
+ destMdDoc.anchor1 = StrCast(sourceMdDoc.anchor2);
+ destMdDoc.anchor2 = StrCast(sourceMdDoc.anchor1);
+ keys.forEach(key => {
+ let val = sourceMdDoc[key] === undefined ? "" : StrCast(sourceMdDoc[key]);
+ destMdDoc[key] = val;
+ });
- this._groups.set(Utils.GenerateGuid(), groupDoc);
+ // create new group doc with new metadata doc
+ let destGroupDoc = new Doc();
+ destGroupDoc.type = groupType;
+ destGroupDoc.metadata = destMdDoc;
- let linkDoc = this.props.linkDoc.proto ? this.props.linkDoc.proto : this.props.linkDoc;
- LinkManager.Instance.setAnchorGroups(linkDoc, this.props.sourceDoc, Array.from(this._groups.values()));
+ LinkManager.Instance.addGroupToAnchor(this.props.linkDoc, destDoc, destGroupDoc, true);
}
@action
- setGroupType = (groupId: string, groupType: string): void => {
- let groupDoc = this._groups.get(groupId);
- if (groupDoc) {
- groupDoc.proto!.type = groupType;
- this._groups.set(groupId, groupDoc);
- LinkManager.Instance.setAnchorGroups(this.props.linkDoc, this.props.sourceDoc, Array.from(this._groups.values()));
- }
- }
-
- removeGroupFromLink = (groupId: string, groupType: string): void => {
- let groupDoc = this._groups.get(groupId);
- if (!groupDoc) console.error("LinkEditor: group not found");
- LinkManager.Instance.removeGroupFromAnchor(this.props.linkDoc, this.props.sourceDoc, groupType);
- this._groups.delete(groupId);
- }
-
- deleteGroup = (groupId: string, groupType: string): void => {
- let groupDoc = this._groups.get(groupId);
- if (!groupDoc) console.error("LinkEditor: group not found");
- LinkManager.Instance.deleteGroup(groupType);
- this._groups.delete(groupId);
+ addMetadata = (groupType: string): void => {
+ let mdKeys = LinkManager.Instance.getMetadataKeysInGroup(groupType);
+ // only add "new key" if there is no other key with value "new key"; prevents spamming
+ if (mdKeys.indexOf("new key") === -1) mdKeys.push("new key");
+ LinkManager.Instance.setMetadataKeysForGroup(groupType, mdKeys);
}
- copyGroup = (groupId: string, groupType: string): void => {
- let sourceGroupDoc = this._groups.get(groupId);
- let sourceMdDoc = Cast(sourceGroupDoc!.metadata, Doc, new Doc);
- let destDoc = LinkManager.Instance.findOppositeAnchor(this.props.linkDoc, this.props.sourceDoc);
- let destGroupList = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, destDoc);
- let keys = LinkManager.Instance.groupMetadataKeys.get(groupType);
-
- // create new metadata doc with copied kvp
- let destMdDoc = Docs.TextDocument();
- destMdDoc.proto!.anchor1 = StrCast(sourceMdDoc.anchor2);
- destMdDoc.proto!.anchor2 = StrCast(sourceMdDoc.anchor1);
- if (keys) {
- keys.forEach(key => {
- let val = sourceMdDoc[key] === undefined ? "" : StrCast(sourceMdDoc[key]);
- destMdDoc[key] = val;
+ renderMetadata = (): JSX.Element[] => {
+ let metadata: Array<JSX.Element> = [];
+ let groupDoc = this.props.groupDoc;
+ let mdDoc = Cast(groupDoc.metadata, Doc, new Doc);
+ let groupType = StrCast(groupDoc.type);
+ let groupMdKeys = LinkManager.Instance.getMetadataKeysInGroup(groupType);
+ if (groupMdKeys) {
+ groupMdKeys.forEach((key, index) => {
+ metadata.push(
+ <LinkMetadataEditor key={"mded-" + index} groupType={groupType} mdDoc={mdDoc} mdKey={key} mdValue={(mdDoc[key] === undefined) ? "" : StrCast(mdDoc[key])} />
+ );
});
}
-
- // create new group doc with new metadata doc
- let destGroupDoc = Docs.TextDocument();
- destGroupDoc.proto!.type = groupType;
- destGroupDoc.proto!.metadata = destMdDoc;
-
- // if group does not already exist on opposite anchor, create group doc
- let index = destGroupList.findIndex(groupDoc => { StrCast(groupDoc.type).toUpperCase() === groupType.toUpperCase(); });
- if (index > -1) {
- destGroupList[index] = destGroupDoc;
- } else {
- destGroupList.push(destGroupDoc);
- }
-
- LinkManager.Instance.setAnchorGroups(this.props.linkDoc, destDoc, destGroupList);
+ return metadata;
}
- viewGroupAsTable = (groupId: string, groupType: string): JSX.Element => {
- let keys = LinkManager.Instance.groupMetadataKeys.get(groupType);
- let groupDoc = this._groups.get(groupId);
- if (keys && groupDoc) {
- let docs: Doc[] = LinkManager.Instance.findAllMetadataDocsInGroup(groupType);
- let createTable = action(() => Docs.SchemaDocument(["anchor1", "anchor2", ...keys!], docs, { width: 200, height: 200, title: groupType + " table" }));
- let ref = React.createRef<HTMLDivElement>();
- return <div ref={ref}><button className="linkEditor-button" onPointerDown={SetupDrag(ref, createTable)}><FontAwesomeIcon icon="table" size="sm" /></button></div>;
- } else {
- return <button className="linkEditor-button" disabled><FontAwesomeIcon icon="table" size="sm" /></button>;
- }
+ viewGroupAsTable = (groupType: string): JSX.Element => {
+ let keys = LinkManager.Instance.getMetadataKeysInGroup(groupType);
+ let docs: Doc[] = LinkManager.Instance.getAllMetadataDocsInGroup(groupType);
+ let createTable = action(() => Docs.SchemaDocument(["anchor1", "anchor2", ...keys], docs, { width: 500, height: 300, title: groupType + " table" }));
+ let ref = React.createRef<HTMLDivElement>();
+ return <div ref={ref}><button className="linkEditor-button" onPointerDown={SetupDrag(ref, createTable)}><FontAwesomeIcon icon="table" size="sm" /></button></div>;
}
- renderGroup = (groupId: string, groupDoc: Doc): JSX.Element => {
- let type = StrCast(groupDoc.type);
- if ((type && LinkManager.Instance.groupMetadataKeys.get(type)) || type === "New Group") {
- let buttons;
- if (type === "New Group") {
- 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(groupId, type)} 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><FontAwesomeIcon icon="table" size="sm" /></button>
- </>
- );
- } else {
- buttons = (
- <>
- <button className="linkEditor-button" onClick={() => this.addMetadata(StrCast(groupDoc.proto!.type))} title="Add KVP"><FontAwesomeIcon icon="plus" size="sm" /></button>
- <button className="linkEditor-button" onClick={() => this.copyGroup(groupId, type)} title="Copy group to opposite anchor"><FontAwesomeIcon icon="exchange-alt" size="sm" /></button>
- <button className="linkEditor-button" onClick={() => this.removeGroupFromLink(groupId, type)} title="Remove group from link"><FontAwesomeIcon icon="times" size="sm" /></button>
- <button className="linkEditor-button" onClick={() => this.deleteGroup(groupId, type)} title="Delete group"><FontAwesomeIcon icon="trash" size="sm" /></button>
- {this.viewGroupAsTable(groupId, type)}
- </>
- );
- }
-
- return (
- <div key={groupId} className="linkEditor-group">
- <div className="linkEditor-group-row">
- <p className="linkEditor-group-row-label">type:</p>
- <GroupTypesDropdown groupId={groupId} groupType={StrCast(groupDoc.proto!.type)} setGroup={this.setGroupType} />
- </div>
- {this.renderMetadata(groupId)}
- <div className="linkEditor-group-buttons">
- {buttons}
- </div>
- </div>
+ render() {
+ let groupType = StrCast(this.props.groupDoc.type);
+ // 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><FontAwesomeIcon icon="table" size="sm" /></button>
+ </>
);
} else {
- return <></>;
+ 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)}
+ </>
+ );
}
+
+ return (
+ <div className="linkEditor-group">
+ <div className="linkEditor-group-row">
+ <p className="linkEditor-group-row-label">type:</p>
+ <GroupTypesDropdown groupType={groupType} setGroupType={this.setGroupType} />
+ </div>
+ {this.renderMetadata()}
+ <div className="linkEditor-group-buttons">
+ {buttons}
+ </div>
+ </div>
+ );
}
+ // else {
+ // return <></>;
+ // }
+ // }
+}
+
+interface LinkEditorProps {
+ sourceDoc: Doc;
+ linkDoc: Doc;
+ showLinks: () => void;
+}
+@observer
+export class LinkEditor extends React.Component<LinkEditorProps> {
@action
- addMetadata = (groupType: string): void => {
- console.log("ADD MD");
- let mdKeys = LinkManager.Instance.groupMetadataKeys.get(groupType);
- if (mdKeys) {
- // only add "new key" if there is no other key with value "new key"; prevents spamming
- if (mdKeys.indexOf("new key") === -1) mdKeys.push("new key");
- } else {
- mdKeys = ["new key"];
- }
- LinkManager.Instance.groupMetadataKeys.set(groupType, mdKeys);
+ deleteLink = (): void => {
+ LinkManager.Instance.deleteLink(this.props.linkDoc);
+ this.props.showLinks();
}
- renderMetadata = (groupId: string): JSX.Element[] => {
- let metadata: Array<JSX.Element> = [];
- let groupDoc = this._groups.get(groupId);
- if (groupDoc) {
- let mdDoc = Cast(groupDoc.proto!.metadata, Doc, new Doc);
- let groupType = StrCast(groupDoc.proto!.type);
- let groupMdKeys = LinkManager.Instance.groupMetadataKeys.get(groupType);
- if (groupMdKeys) {
- groupMdKeys.forEach((key, index) => {
- metadata.push(
- <LinkMetadataEditor key={"mded-" + index} groupType={groupType} mdDoc={mdDoc} mdKey={key} mdValue={(mdDoc[key] === undefined) ? "" : StrCast(mdDoc[key])} />
- );
- });
- }
- }
- return metadata;
+ @action
+ addGroup = (): void => {
+ // create new metadata document for group
+ let mdDoc = new Doc();
+ mdDoc.anchor1 = this.props.sourceDoc.title;
+ mdDoc.anchor2 = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc).title;
+
+ // create new group document
+ let groupDoc = new Doc();
+ groupDoc.type = "";
+ groupDoc.metadata = mdDoc;
+
+ LinkManager.Instance.addGroupToAnchor(this.props.linkDoc, this.props.sourceDoc, groupDoc);
}
render() {
- let destination = LinkManager.Instance.findOppositeAnchor(this.props.linkDoc, this.props.sourceDoc);
+ let destination = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc);
- let groups: Array<JSX.Element> = [];
- this._groups.forEach((groupDoc, groupId) => {
- groups.push(this.renderGroup(groupId, groupDoc));
+ let groupList = LinkManager.Instance.getAnchorGroups(this.props.linkDoc, this.props.sourceDoc);
+ console.log("NUM GROUPS", groupList.length);
+ let groups = groupList.map(groupDoc => {
+ return <LinkGroupEditor key={"gred-" + StrCast(groupDoc.type)} linkDoc={this.props.linkDoc} sourceDoc={this.props.sourceDoc} groupDoc={groupDoc} />;
});
+
+ // let groups: Array<JSX.Element> = [];
+ // this._groups.forEach((groupDoc, groupId) => {
+ // groups.push(this.renderGroup(groupId, groupDoc));
+ // });
+
return (
<div className="linkEditor">
<button className="linkEditor-back" onPointerDown={() => this.props.showLinks()}><FontAwesomeIcon icon="arrow-left" size="sm" /></button>
diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx
index f96c7d2e4..04ca47db3 100644
--- a/src/client/views/nodes/LinkMenu.tsx
+++ b/src/client/views/nodes/LinkMenu.tsx
@@ -38,7 +38,7 @@ export class LinkMenu extends React.Component<Props> {
render() {
let sourceDoc = this.props.docView.props.Document;
- let groups: Map<string, Doc[]> = LinkManager.Instance.findRelatedGroupedLinks(sourceDoc);
+ let groups: Map<string, Doc[]> = LinkManager.Instance.getRelatedGroupedLinks(sourceDoc);
if (this._editingLink === undefined) {
return (
<div className="linkMenu">
diff --git a/src/client/views/nodes/LinkMenuGroup.tsx b/src/client/views/nodes/LinkMenuGroup.tsx
index 229143d99..71326f703 100644
--- a/src/client/views/nodes/LinkMenuGroup.tsx
+++ b/src/client/views/nodes/LinkMenuGroup.tsx
@@ -42,10 +42,10 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
document.removeEventListener("pointermove", this.onLinkButtonMoved);
document.removeEventListener("pointerup", this.onLinkButtonUp);
- let draggedDocs = this.props.group.map(linkDoc => LinkManager.Instance.findOppositeAnchor(linkDoc, this.props.sourceDoc));
+ let draggedDocs = this.props.group.map(linkDoc => LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc));
let dragData = new DragManager.DocumentDragData(draggedDocs);
- DragManager.StartLinkedDocumentDrag([this._drag.current], dragData, e.x, e.y, {
+ DragManager.StartLinkedDocumentDrag([this._drag.current], this.props.sourceDoc, dragData, e.x, e.y, {
handlers: {
dragComplete: action(emptyFunction),
},
@@ -57,7 +57,7 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
render() {
let groupItems = this.props.group.map(linkDoc => {
- let destination = LinkManager.Instance.findOppositeAnchor(linkDoc, this.props.sourceDoc);
+ let destination = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc);
return <LinkMenuItem key={destination[Id] + this.props.sourceDoc[Id]} groupType={this.props.groupType}
linkDoc={linkDoc} sourceDoc={this.props.sourceDoc} destinationDoc={destination} showEditor={this.props.showEditor} />;
});
@@ -69,6 +69,6 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
{groupItems}
</div>
</div>
- )
+ );
}
} \ No newline at end of file
diff --git a/src/client/views/nodes/LinkMenuItem.tsx b/src/client/views/nodes/LinkMenuItem.tsx
index 42ef353b7..28694721d 100644
--- a/src/client/views/nodes/LinkMenuItem.tsx
+++ b/src/client/views/nodes/LinkMenuItem.tsx
@@ -53,8 +53,8 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
let mdRows: Array<JSX.Element> = [];
if (groupDoc) {
let mdDoc = Cast(groupDoc.metadata, Doc, new Doc);
- let keys = LinkManager.Instance.groupMetadataKeys.get(this.props.groupType);
- mdRows = keys!.map(key => {
+ let 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>);
});
}
@@ -88,7 +88,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
render() {
- let keys = LinkManager.Instance.groupMetadataKeys.get(this.props.groupType);
+ let keys = LinkManager.Instance.getMetadataKeysInGroup(this.props.groupType);//groupMetadataKeys.get(this.props.groupType);
let canExpand = keys ? keys.length > 0 : false;
return (