From d429898b5337331450e46c223380e5d00967b2d6 Mon Sep 17 00:00:00 2001
From: Fawn <fangrui_tong@brown.edu>
Date: Mon, 10 Jun 2019 20:02:32 -0400
Subject: added set up for metadata on links

---
 src/client/views/nodes/LinkEditor.tsx | 229 ++++++++++++++++++++++++++++------
 1 file changed, 188 insertions(+), 41 deletions(-)

(limited to 'src/client/views/nodes/LinkEditor.tsx')

diff --git a/src/client/views/nodes/LinkEditor.tsx b/src/client/views/nodes/LinkEditor.tsx
index 2ab8c3460..14fdd26df 100644
--- a/src/client/views/nodes/LinkEditor.tsx
+++ b/src/client/views/nodes/LinkEditor.tsx
@@ -10,17 +10,57 @@ import { StrCast, Cast } from "../../../new_fields/Types";
 import { Doc } from "../../../new_fields/Doc";
 import { List } from "../../../new_fields/List";
 import { listSpec } from "../../../new_fields/Schema";
-import { LinkManager } from "../../util/LinkManager";
+import { LinkManager, LinkUtils } from "../../util/LinkManager";
+import { Docs } from "../../documents/Documents";
+import { Utils } from "../../../Utils";
+import { faArrowLeft, faEllipsisV } from '@fortawesome/free-solid-svg-icons';
+import { library } from "@fortawesome/fontawesome-svg-core";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { string } from "prop-types";
 
-interface Props {
+library.add(faArrowLeft);
+library.add(faEllipsisV);
+
+interface LinkEditorProps {
     sourceDoc: Doc;
     linkDoc: Doc;
-    groups: Map<number, Doc>;
+    groups: Map<string, Doc>;
+    metadata: Map<string, Map<string, Doc>>;
     showLinks: () => void;
 }
 
 @observer
-export class LinkEditor extends React.Component<Props> {
+export class LinkEditor extends React.Component<LinkEditorProps> {
+
+    // @observable private _groups: Map<string, Doc> = new Map();
+    // @observable private _metadata: Map<string, Map<string, Doc>> = new Map();
+
+    // // componentDidMount() {
+
+    // // }
+    // constructor(props: LinkEditorProps) {
+    //     super(props);
+
+    //     let groups = new Map<string, Doc>();
+    //     let metadata: Map<string, Map<string, Doc>> = new Map();
+    //     let groupList = (Doc.AreProtosEqual(props.docView.props.Document, Cast(this._editingLink.anchor1, Doc, new Doc))) ?
+    //         Cast(this._editingLink.anchor1Groups, listSpec(Doc), []) : Cast(this._editingLink.anchor2Groups, listSpec(Doc), []);
+    //     groupList.forEach(groupDoc => {
+    //         if (groupDoc instanceof Doc) {
+    //             let id = Utils.GenerateGuid();
+    //             groups.set(id, groupDoc);
+
+    //             let metadataMap = new Map<string, Doc>();
+    //             let metadataDocs = Cast(groupDoc.proto!.metadata, listSpec(Doc), []);
+    //             metadataDocs.forEach(mdDoc => {
+    //                 if (mdDoc && mdDoc instanceof Doc) { // TODO: handle promise doc
+    //                     metadataMap.set(Utils.GenerateGuid(), mdDoc);
+    //                 }
+    //             })
+    //             metadata.set(id, metadataMap);
+    //         }
+    //     })
+    // }
 
     // @observable private _title: string = StrCast(this.props.linkDoc.title);
     // @observable private _description: string = StrCast(this.props.linkDoc.linkDescription);
@@ -51,68 +91,175 @@ export class LinkEditor extends React.Component<Props> {
     // }
 
     @action
-    editGroup(groupId: number, value: string) {
+    editGroup(groupId: string, value: string) {
         let linkDoc = this.props.linkDoc.proto ? this.props.linkDoc.proto : this.props.linkDoc;
         let groupDoc = this.props.groups.get(groupId);
         if (groupDoc) {
             groupDoc.proto!.type = value;
-            if (Doc.AreProtosEqual(this.props.sourceDoc, Cast(linkDoc.anchor1, Doc, new Doc))) {
-                // let groups = Cast(linkDoc.anchor1Groups, listSpec(Doc), []);
-                // groups.push(groupDoc);
-                linkDoc.anchor1Groups = new List<Doc>([groupDoc]);
-
-            } else {
-                linkDoc.anchor2Groups = new List<Doc>([groupDoc]);
-            }
+            LinkUtils.setAnchorGroups(linkDoc, this.props.sourceDoc, [groupDoc]);
         }
+    }
+
+    @action
+    addGroup = (e: React.MouseEvent): void => {
+        // create new document for group
+        let groupDoc = Docs.TextDocument();
+        groupDoc.proto!.title = "";
+        groupDoc.proto!.metadata = new List<Doc>([]);
 
+        this.props.groups.set(Utils.GenerateGuid(), groupDoc);
+
+        let linkDoc = this.props.linkDoc.proto ? this.props.linkDoc.proto : this.props.linkDoc;
+        LinkUtils.setAnchorGroups(linkDoc, this.props.sourceDoc, Array.from(this.props.groups.values()));
     }
 
-    renderGroup(groupId: number, groupDoc: Doc) {
+    renderGroup(groupId: string, groupDoc: Doc) {
+        // let metadata = this.props.metadata.get(groupId);
+        // if (!metadata) {
+        //     metadata = new Map<string, Doc>();
+        // }
         return (
-            <div>
-                <p>type:</p>
-                <input type="text" value={StrCast(groupDoc.proto!.type)} onChange={e => this.editGroup(groupId, e.target.value)}></input>
+            // <div key={groupId} className="linkEditor-group">
+            <div key={groupId} className="linkEditor-group-row">
+                <p className="linkEditor-group-row-label">type:</p>
+                <input key={groupId + "-type"} type="text" value={StrCast(groupDoc.proto!.type)} onChange={e => this.editGroup(groupId, e.target.value)}></input>
             </div>
+            //         {/* {this.renderMetadata(groupId)} */ }
+            // {/* <button onPointerDown={() => this.addMetadata(groupId)}>+</button> */ }
+            //     // </div>
         )
     }
 
+    @action
+    addMetadata = (groupId: string): void => {
+        // create new metadata doc
+        let mdDoc = Docs.TextDocument();
+        mdDoc.proto!.title = "";
+        mdDoc.proto!.value = "";
+
+        // append to map
+        let mdMap = this.props.metadata.get(groupId);
+        if (mdMap) {
+            mdMap.set(Utils.GenerateGuid(), mdDoc);
+        } else {
+            mdMap = new Map();
+            mdMap.set(Utils.GenerateGuid(), mdDoc);
+        }
+
+        // add to internal representation of metadata
+        this.props.metadata.set(groupId, mdMap);
+
+        // add to internatal representation of group
+        let groupDoc = this.props.groups.get(groupId);
+        if (groupDoc) {
+            groupDoc.proto!.metadata = new List<Doc>(Array.from(mdMap.values()));
+            this.props.groups.set(groupId, groupDoc);
+        }
+
+        // add to link doc
+        let linkDoc = this.props.linkDoc.proto ? this.props.linkDoc.proto : this.props.linkDoc;
+        LinkUtils.setAnchorGroups(linkDoc, this.props.sourceDoc, Array.from(this.props.groups.values()));
+
+    }
+
+    // @action
+    // addMetadata = (groupId: string): void => {
+    //     let groupDoc = this.props.groups.get(groupId);
+    //     if (groupDoc) {
+    //         // create new document for metadata row
+    //         let metadata = Cast(groupDoc.metadata, listSpec(Doc), []);
+    //         let metadataDoc = Docs.TextDocument();
+    //         metadataDoc.proto!.title = "";
+    //         metadataDoc.proto!.value = "";
+    //         let metadataMap = new Map<string, 
+
+    //         this.props.metadata.set(groupId, new Map)
+
+    //         groupDoc.proto!.metadata = new List<Doc>([metadataDoc]); // TODO: append to metadata
+    //     }
+    // }
+
+    // @action
+    // editMetadataTitle = (groupId: string, mdId: string, value: string) => {
+    //     let group = this.props.metadata.get(groupId);
+    //     if (group) {
+    //         let mdDoc = group.get(mdId);
+    //         if (mdDoc) {
+    //             mdDoc.proto!.title = value;
+    //         }
+    //     }
+    // }
+
+    // @action
+    // editMetadataValue = (groupId: string, mdId: string, value: string) => {
+    //     let group = this.props.metadata.get(groupId);
+    //     if (group) {
+    //         let mdDoc = group.get(mdId);
+    //         if (mdDoc) {
+    //             mdDoc.proto!.value = value;
+    //         }
+    //     }
+    // }
+
+    @action
+    editMetadataTitle(groupId: string, mdId: string, value: string) {
+
+    }
+
+    @action
+    editMetadataValue(groupId: string, mdId: string, value: string) {
+
+    }
+
+    renderMetadata(groupId: string) {
+        let metadata: Array<JSX.Element> = [];
+        let metadataMap = this.props.metadata.get(groupId);
+        if (metadataMap) {
+            metadataMap.forEach((mdDoc, mdId) => {
+                metadata.push(
+                    <div key={mdId} className="linkEditor-metadata-row">
+                        <input type="text" value={StrCast(mdDoc.proto!.title)} onChange={e => this.editMetadataTitle(groupId, mdId, e.target.value)}></input>
+                        :
+                        <input type="text" value={StrCast(mdDoc.proto!.value)} onChange={e => this.editMetadataValue(groupId, mdId, e.target.value)}></input>
+                    </div>
+                )
+            })
+        }
+
+        return metadata;
+
+        // let metadataList: Array<JSX.Element> = [];
+        // metadata.forEach((mdDoc, mdId) => {
+        //     metadataList.push(
+        //         <div key={mdId} className="linkEditor-metadata-row">
+        //             <input type="text" value={StrCast(mdDoc.proto!.title)} onChange={e => this.editMetadataTitle(groupId, mdId, e.target.value)}></input>:
+        //             <input type="text" value={StrCast(mdDoc.proto!.value)} onChange={e => this.editMetadataValue(groupId, mdId, e.target.value)}></input>
+        //         </div>
+        //     )
+        // })
+    }
+
     renderGroups() {
         let groups: Array<JSX.Element> = [];
         this.props.groups.forEach((groupDoc, groupId) => {
-            groups.push(
-                <div>
-                    {this.renderGroup(groupId, groupDoc)}
-                </div>
-            )
+            groups.push(this.renderGroup(groupId, groupDoc))
         });
         return groups;
     }
 
-    onSaveButtonPressed = (e: React.PointerEvent): void => {
-        e.stopPropagation();
-
-        // let linkDoc = this.props.linkDoc.proto ? this.props.linkDoc.proto : this.props.linkDoc;
-        // // linkDoc.title = this._title;
-        // // linkDoc.linkDescription = this._description;
-
-        this.props.showLinks();
-    }
-
     render() {
-        let destination = LinkManager.Instance.findOppositeAnchor(this.props.linkDoc, this.props.sourceDoc);
+        let destination = LinkUtils.findOppositeAnchor(this.props.linkDoc, this.props.sourceDoc);
 
         return (
-            <div className="edit-container">
-                <p>linked to: {destination.proto!.title}</p>
-                <b>Groups:</b>
+            <div className="linkEditor">
+                <button className="linkEditor-back" onPointerDown={() => this.props.showLinks()}><FontAwesomeIcon icon="arrow-left" size="sm" /></button>
+                <p className="linkEditor-linkedTo">editing link to: <b>{destination.proto!.title}</b></p>
+                <div className="linkEditor-groupsLabel">
+                    <b>Groups:</b>
+                    <button onClick={this.addGroup} title="Add Group">+</button>
+                </div>
                 {this.renderGroups()}
 
-                {/* <input onChange={this.onTitleChanged} className="name-input" type="text" value={this._title} placeholder="Name . . ."></input>
-                <textarea onChange={this.onDescriptionChanged} className="description-input" value={this._description} placeholder="Description . . ."></textarea> */}
-                {/* {this.renderTags()}
-                <button onClick={this.addTag}>+</button> */}
-                <div className="save-button" onPointerDown={this.onSaveButtonPressed}>SAVE</div>
             </div>
 
         );
-- 
cgit v1.2.3-70-g09d2

