From f90b7ca17a9f45aa6c47f1d7a37d09af4d44d2ad Mon Sep 17 00:00:00 2001
From: madelinegr <laura_wilson@brown.edu>
Date: Wed, 27 Feb 2019 00:38:39 -0500
Subject: kvp almost done

---
 src/client/views/collections/CollectionFreeFormView.tsx | 6 ++++++
 1 file changed, 6 insertions(+)

(limited to 'src/client/views/collections/CollectionFreeFormView.tsx')

diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 12909c151..ded1e3785 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -163,6 +163,11 @@ export class CollectionFreeFormView extends CollectionViewBase {
         });
     }
 
+    @action
+    addKVP(doc: Document) {
+        let fields = doc.fields;
+        // aefawefwaef
+    }
 
     @computed get backgroundLayout(): string | undefined {
         let field = this.props.Document.GetT(KeyStore.BackgroundLayout, TextField);
@@ -241,6 +246,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
                     {this.backgroundView}
                     {this.views}
                 </div>
+                <!-- put fale stuff here>
                 {this.overlayView}
             </div>
         );
-- 
cgit v1.2.3-70-g09d2


From 7087091612e39344c88f96eca12172a1045391bc Mon Sep 17 00:00:00 2001
From: madelinegr <laura_wilson@brown.edu>
Date: Wed, 27 Feb 2019 00:47:13 -0500
Subject: kvp almost done+1

---
 src/client/views/collections/CollectionFreeFormView.tsx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'src/client/views/collections/CollectionFreeFormView.tsx')

diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index ded1e3785..5a5f9197d 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -166,7 +166,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
     @action
     addKVP(doc: Document) {
         let fields = doc.fields;
-        // aefawefwaef
+        //TODO: return kvp
     }
 
     @computed get backgroundLayout(): string | undefined {
@@ -229,6 +229,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
     noScaling = () => 1;
 
     render() {
+        //TODO: put KVP stuff in this function
         const panx: number = this.props.Document.GetNumber(KeyStore.PanX, 0) + this.centeringShiftX;
         const pany: number = this.props.Document.GetNumber(KeyStore.PanY, 0) + this.centeringShiftY;
         return (
@@ -246,7 +247,6 @@ export class CollectionFreeFormView extends CollectionViewBase {
                     {this.backgroundView}
                     {this.views}
                 </div>
-                <!-- put fale stuff here>
                 {this.overlayView}
             </div>
         );
-- 
cgit v1.2.3-70-g09d2


From 6d96342814874fe5ceec7264887a37e8aa1fab20 Mon Sep 17 00:00:00 2001
From: madelinegr <laura_wilson@brown.edu>
Date: Wed, 27 Feb 2019 00:54:57 -0500
Subject: kvp almost done +2

---
 src/client/views/collections/CollectionFreeFormView.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'src/client/views/collections/CollectionFreeFormView.tsx')

diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 5a5f9197d..e00201629 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -166,7 +166,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
     @action
     addKVP(doc: Document) {
         let fields = doc.fields;
-        //TODO: return kvp
+        //TODO: return kvpg
     }
 
     @computed get backgroundLayout(): string | undefined {
-- 
cgit v1.2.3-70-g09d2


From 23387df535e9ab87a08196aab19de6f937ae9bba Mon Sep 17 00:00:00 2001
From: madelinegr <laura_wilson@brown.edu>
Date: Thu, 28 Feb 2019 00:20:14 -0500
Subject: finished kvp

---
 package-lock.json                                  |  21 +--
 package.json                                       |   2 +-
 src/client/documents/Documents.ts                  |  16 ++
 .../views/collections/CollectionFreeFormView.tsx   |   7 -
 src/client/views/nodes/DocumentView.tsx            |  14 +-
 src/client/views/nodes/FieldView.tsx               |   2 +
 src/client/views/nodes/KeyValuePair.tsx            |  68 ++++++++
 src/client/views/nodes/KeyValuePane.tsx            | 176 +++++++++------------
 src/fields/KVPField                                |   0
 src/fields/KVPField.ts                             |  30 ++++
 10 files changed, 198 insertions(+), 138 deletions(-)
 create mode 100644 src/client/views/nodes/KeyValuePair.tsx
 create mode 100644 src/fields/KVPField
 create mode 100644 src/fields/KVPField.ts

(limited to 'src/client/views/collections/CollectionFreeFormView.tsx')

diff --git a/package-lock.json b/package-lock.json
index d03e78a2d..75e6cae17 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3285,11 +3285,6 @@
         }
       }
     },
-    "font-awesome": {
-      "version": "4.7.0",
-      "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz",
-      "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM="
-    },
     "for-in": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
@@ -3399,13 +3394,11 @@
         },
         "balanced-match": {
           "version": "1.0.0",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "brace-expansion": {
           "version": "1.1.11",
           "bundled": true,
-          "optional": true,
           "requires": {
             "balanced-match": "^1.0.0",
             "concat-map": "0.0.1"
@@ -3422,8 +3415,7 @@
         },
         "concat-map": {
           "version": "0.0.1",
-          "bundled": true,
-          "optional": true
+          "bundled": true
         },
         "console-control-strings": {
           "version": "1.1.0",
@@ -3552,7 +3544,6 @@
         "minimatch": {
           "version": "3.0.4",
           "bundled": true,
-          "optional": true,
           "requires": {
             "brace-expansion": "^1.1.7"
           }
@@ -10434,14 +10425,6 @@
         "scheduler": "^0.12.0"
       }
     },
-    "react-fontawesome": {
-      "version": "1.6.1",
-      "resolved": "https://registry.npmjs.org/react-fontawesome/-/react-fontawesome-1.6.1.tgz",
-      "integrity": "sha1-7dzhfn3HMaoJ/UoYZoimF5OhbFw=",
-      "requires": {
-        "prop-types": "^15.5.6"
-      }
-    },
     "react-golden-layout": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/react-golden-layout/-/react-golden-layout-1.0.6.tgz",
diff --git a/package.json b/package.json
index 8568a7bef..ae7a7b25c 100644
--- a/package.json
+++ b/package.json
@@ -116,4 +116,4 @@
     "url-loader": "^1.1.2",
     "uuid": "^3.3.2"
   }
-}
\ No newline at end of file
+}
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index ba13cc31b..41f1c9b3f 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -13,6 +13,8 @@ import { CollectionView, CollectionViewType } from "../views/collections/Collect
 import { HtmlField } from "../../fields/HtmlField";
 import { Key } from "../../fields/Key"
 import { Field } from "../../fields/Field";
+import { KeyValuePane } from "../views/nodes/KeyValuePane"
+import { KVPField } from "../../fields/KVPField";
 
 export interface DocumentOptions {
     x?: number;
@@ -35,10 +37,12 @@ export namespace Documents {
     let imageProto: Document;
     let webProto: Document;
     let collProto: Document;
+    let kvpProto: Document;
     const textProtoId = "textProto";
     const imageProtoId = "imageProto";
     const webProtoId = "webProto";
     const collProtoId = "collectionProto";
+    const kvpProtoId = "kvpProto";
 
     export function initProtos(mainDocId: string, callback: (mainDoc?: Document) => void) {
         Server.GetFields([collProtoId, textProtoId, imageProtoId, mainDocId], (fields) => {
@@ -46,6 +50,7 @@ export namespace Documents {
             imageProto = fields[imageProtoId] as Document;
             textProto = fields[textProtoId] as Document;
             webProto = fields[webProtoId] as Document;
+            kvpProto = fields[kvpProtoId] as Document;
             callback(fields[mainDocId] as Document)
         });
     }
@@ -98,6 +103,12 @@ export namespace Documents {
                 { panx: 0, pany: 0, scale: 1, layoutKeys: [KeyStore.Data] });
     }
 
+    function GetKVPPrototype(): Document {
+        return kvpProto ? kvpProto :
+            kvpProto = setupPrototypeOptions(kvpProtoId, "KVP_PROTO", KeyValuePane.LayoutString(),
+                { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] })
+    }
+
     export function ImageDocument(url: string, options: DocumentOptions = {}) {
         let doc = SetInstanceOptions(GetImagePrototype(), { ...options, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] },
             new URL(url), ImageField);
@@ -124,6 +135,11 @@ export namespace Documents {
     export function DockDocument(config: string, options: DocumentOptions, id?: string) {
         return SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Docking }, config, TextField, id)
     }
+    export function KVPDocument(document: Document, options: DocumentOptions = {}, id?: string) {
+        var deleg = GetKVPPrototype().MakeDelegate(id);
+        deleg.Set(KeyStore.Data, document);
+        return assignOptions(deleg, options);
+    }
 
 
 
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 29d254e56..137bcf706 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -194,12 +194,6 @@ export class CollectionFreeFormView extends CollectionViewBase {
         });
     }
 
-    @action
-    addKVP(doc: Document) {
-        let fields = doc.fields;
-        //TODO: return kvpg
-    }
-
     @computed get backgroundLayout(): string | undefined {
         let field = this.props.Document.GetT(KeyStore.BackgroundLayout, TextField);
         if (field && field !== "<Waiting>") {
@@ -266,7 +260,6 @@ export class CollectionFreeFormView extends CollectionViewBase {
     }
 
     render() {
-        //TODO: put KVP stuff in this function
 
         //determines whether preview text cursor should be visible (ie when user taps this collection it should)
         let cursor = null;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index d1706c80c..23cfa6df3 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -20,13 +20,9 @@ import { KeyValuePane } from "../nodes/KeyValuePane"
 import { WebBox } from "../nodes/WebBox";
 import "./DocumentView.scss";
 import React = require("react");
+import { CollectionViewProps } from "../collections/CollectionViewBase";
 const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this?
 
-/*
-    if containingcollectionview is CollectionFreeformView:
-        (ContainingCollectionView as CollectionFreeformView)?.addKVP
-*/
-
 
 export interface DocumentViewProps {
     ContainingCollectionView: Opt<CollectionView>;
@@ -161,8 +157,8 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     }
 
     fieldsClicked = (e: React.MouseEvent): void => {
-        if (this.props.ContainingCollectionView) {
-            (this.props.ContainingCollectionView as unknown as CollectionFreeFormView).addKVP(this.props.Document);
+        if (this.props.AddDocument) {
+            this.props.AddDocument(Documents.KVPDocument(this.props.Document));
         }
     }
     fullScreenClicked = (e: React.MouseEvent): void => {
@@ -190,7 +186,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         e.preventDefault()
 
         ContextMenu.Instance.addItem({ description: "Full Screen", event: this.fullScreenClicked })
-        ContextMenu.Instance.addItem({ description: "Fields", event: () => this.fieldsClicked })
+        ContextMenu.Instance.addItem({ description: "Fields", event: this.fieldsClicked })
         ContextMenu.Instance.addItem({ description: "Open Right", event: () => CollectionDockingView.Instance.AddRightSplit(this.props.Document) })
         ContextMenu.Instance.addItem({ description: "Freeform", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform) })
         ContextMenu.Instance.addItem({ description: "Schema", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Schema) })
@@ -209,7 +205,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
 
     @computed get mainContent() {
         return <JsxParser
-            components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox }}
+            components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValuePane }}
             bindings={this._documentBindings}
             jsx={this.layout}
             showWarnings={true}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index f372258f8..056f834d1 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -12,6 +12,8 @@ import { Key } from "../../../fields/Key";
 import { FormattedTextBox } from "./FormattedTextBox";
 import { ImageBox } from "./ImageBox";
 import { WebBox } from "./WebBox";
+import { KVPField } from "../../../fields/KVPField";
+import { KeyValuePane } from "./KeyValuePane";
 
 //
 // these properties get assigned through the render() method of the DocumentView when it creates this node.
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
new file mode 100644
index 000000000..bc407f137
--- /dev/null
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -0,0 +1,68 @@
+import Lightbox from 'react-image-lightbox';
+import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app
+import "./KeyValuePane.scss";
+import React = require("react")
+import { FieldViewProps, FieldView } from './FieldView';
+import { FieldWaiting, Opt, Field } from '../../../fields/Field';
+import { observer } from "mobx-react"
+import { observable, action, IReactionDisposer, reaction, ObservableMap } from 'mobx';
+import { KeyStore } from '../../../fields/KeyStore';
+import { RichTextField } from "../../../fields/RichTextField";
+import { element } from 'prop-types';
+import { props } from 'bluebird';
+import { EditorView } from 'prosemirror-view';
+import { Transaction, EditorState } from 'prosemirror-state';
+import { schema } from 'prosemirror-schema-basic';
+import { keymap } from 'prosemirror-keymap';
+import { undo, redo } from 'prosemirror-history';
+import { baseKeymap } from 'prosemirror-commands';
+import { KVPField } from '../../../fields/KVPField';
+import { Document } from '../../../fields/Document';
+import { Key } from '../../../fields/Key';
+import { JSXElement } from 'babel-types';
+import { Server } from "../../Server"
+
+// Represents one row in a key value plane
+
+export interface KeyValuePairProps {
+    fieldId: string;
+    doc: Document;
+}
+@observer
+export class KeyValuePair extends React.Component<KeyValuePairProps> {
+
+    @observable
+    private key: Opt<Key>
+
+    constructor(props: KeyValuePairProps) {
+        super(props);
+        Server.GetField(this.props.fieldId,
+            action((field: Opt<Field>) => {
+                if (field) {
+                    this.key = field as Key;
+                }
+            }));
+
+    }
+
+
+
+    render() {
+        if (!this.key) {
+            return <tr><td>error</td><td></td></tr>
+
+        }
+        let props: FieldViewProps = {
+            doc: this.props.doc,
+            fieldKey: this.key,
+            isSelected: () => false,
+            select: () => { },
+            isTopMost: false,
+            bindings: {},
+            selectOnLoad: false,
+        }
+        return (
+            <tr><td>{this.key.Name}</td><td><FieldView {...props} /></td></tr>
+        )
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/nodes/KeyValuePane.tsx b/src/client/views/nodes/KeyValuePane.tsx
index 26d5ed9fd..90f5b653c 100644
--- a/src/client/views/nodes/KeyValuePane.tsx
+++ b/src/client/views/nodes/KeyValuePane.tsx
@@ -4,121 +4,93 @@ import 'react-image-lightbox/style.css'; // This only needs to be imported once
 import "./KeyValuePane.scss";
 import React = require("react")
 import { FieldViewProps, FieldView } from './FieldView';
-import { FieldWaiting } from '../../../fields/Field';
+import { FieldWaiting, Opt, Field } from '../../../fields/Field';
 import { observer } from "mobx-react"
-import { observable, action } from 'mobx';
+import { observable, action, IReactionDisposer, reaction, ObservableMap } from 'mobx';
 import { KeyStore } from '../../../fields/KeyStore';
+import { RichTextField } from "../../../fields/RichTextField";
 import { element } from 'prop-types';
 import { props } from 'bluebird';
+import { EditorView } from 'prosemirror-view';
+import { Transaction, EditorState } from 'prosemirror-state';
+import { schema } from 'prosemirror-schema-basic';
+import { keymap } from 'prosemirror-keymap';
+import { undo, redo } from 'prosemirror-history';
+import { baseKeymap } from 'prosemirror-commands';
+import { KVPField } from '../../../fields/KVPField';
+import { Document } from '../../../fields/Document';
+import { Key } from '../../../fields/Key';
+import { JSXElement } from 'babel-types';
+import { KeyValuePair } from "./KeyValuePair"
 
 @observer
-export class KeyValuePane extends React.Component/*<FieldViewProps>*/ {
+export class KeyValuePane extends React.Component<FieldViewProps> {
 
-    public static LayoutString() { return FieldView.LayoutString(KeyValuePane) }
-    //private _ref: React.RefObject<HTMLDivElement>;
-    // private _downX: number = 0;
-    // private _downY: number = 0;
-    // private _lastTap: number = 0;
-    // @observable private _photoIndex: number = 0;
-    // @observable private _isOpen: boolean = false;
+    public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(KeyValuePane, fieldStr) }
+    private _ref: React.RefObject<HTMLDivElement>;
+    private _editorView: Opt<EditorView>;
+    private _reactionDisposer: Opt<IReactionDisposer>;
 
-    constructor() {
+
+    constructor(props: FieldViewProps) {
         super(props);
+
+        this._ref = React.createRef();
+    }
+
+
+
+    shouldComponentUpdate() {
+        return false;
+    }
+
+
+    onPointerDown = (e: React.PointerEvent): void => {
+        if (e.buttons === 1 && this.props.isSelected()) {
+            e.stopPropagation();
+        }
+    }
+    onPointerWheel = (e: React.WheelEvent): void => {
+        e.stopPropagation();
+    }
+
+    createTable = () => {
+        let table: Array<JSX.Element> = []
+        let ret = "waiting"
+        let doc = this.props.doc.GetT(KeyStore.Data, Document);
+        if (!doc || doc == "<Waiting>") {
+            return <tr><td>Loading...</td></tr>
+        }
+        let realDoc = doc;
+
+        let ids: { [key: string]: string } = {};
+        let protos = doc.GetAllPrototypes();
+        for (const proto of protos) {
+            proto._proxies.forEach((val, key) => {
+                if (!(key in ids)) {
+                    ids[key] = key;
+                }
+            })
+        }
+
+        let rows: JSX.Element[] = [];
+        for (let key in ids) {
+            rows.push(<KeyValuePair doc={realDoc} fieldId={key} />)
+        }
+        return rows;
     }
-    // constructor(props: FieldViewProps) {
-    //     super(props);
-
-    //     //     this._ref = React.createRef();
-    //     //     this._imgRef = React.createRef();
-    //     //     this.state = {
-    //     //         photoIndex: 0,
-    //     //         isOpen: false,
-    //     //     };
-    // }
-
-    // @action
-    // onLoad = (target: any) => {
-    //     var h = this._imgRef.current!.naturalHeight;
-    //     var w = this._imgRef.current!.naturalWidth;
-    //     this.props.doc.SetNumber(KeyStore.NativeHeight, this.props.doc.GetNumber(KeyStore.NativeWidth, 0) * h / w)
-    // }
-
-    // componentDidMount() {
-    // }
-
-    // componentWillUnmount() {
-    // }
-
-    // onPointerDown = (e: React.PointerEvent): void => {
-    //     if (Date.now() - this._lastTap < 300) {
-    //         if (e.buttons === 1 && this.props.isSelected()) {
-    //             e.stopPropagation();
-    //             this._downX = e.clientX;
-    //             this._downY = e.clientY;
-    //             document.removeEventListener("pointerup", this.onPointerUp);
-    //             document.addEventListener("pointerup", this.onPointerUp);
-    //         }
-    //     } else {
-    //         this._lastTap = Date.now();
-    //     }
-    // }
-    // @action
-    // onPointerUp = (e: PointerEvent): void => {
-    //     document.removeEventListener("pointerup", this.onPointerUp);
-    //     if (Math.abs(e.clientX - this._downX) < 2 && Math.abs(e.clientY - this._downY) < 2) {
-    //         this._isOpen = true;
-    //     }
-    //     e.stopPropagation();
-    // }
-
-    // lightbox = (path: string) => {
-    //     const images = [path, "http://www.cs.brown.edu/~bcz/face.gif"];
-    //     if (this._isOpen && this.props.isSelected()) {
-    //         return (<Lightbox
-    //             mainSrc={images[this._photoIndex]}
-    //             nextSrc={images[(this._photoIndex + 1) % images.length]}
-    //             prevSrc={images[(this._photoIndex + images.length - 1) % images.length]}
-    //             onCloseRequest={action(() =>
-    //                 this._isOpen = false
-    //             )}
-    //             onMovePrevRequest={action(() =>
-    //                 this._photoIndex = (this._photoIndex + images.length - 1) % images.length
-    //             )}
-    //             onMoveNextRequest={action(() =>
-    //                 this._photoIndex = (this._photoIndex + 1) % images.length
-    //             )}
-    //         />)
-    //     }
-    // }
+
 
     render() {
-        //     let field = this.props.doc.Get(this.props.fieldKey);
-        //     let path = field == FieldWaiting ? "https://image.flaticon.com/icons/svg/66/66163.svg" :
-        //         field instanceof ImageField ? field.Data.href : "http://www.cs.brown.edu/~bcz/face.gif";
-        //     let nativeWidth = this.props.doc.GetNumber(KeyStore.NativeWidth, 1);
-        //     return (
-        //         <div className="imageBox-cont" onPointerDown={this.onPointerDown} ref={this._ref} >
-        //             <img src={path} width={nativeWidth} alt="Image not found" ref={this._imgRef} onLoad={this.onLoad} />
-        //             {this.lightbox(path)}
-        //         </div>)
-        console.log("bleh");
+
         return (<table>
-            <tr>
-                <th>Key</th>
-                <th>Fields</th>
-            </tr>
-            <tr>
-                <td>Jill</td>
-                <td>Smith</td>
-            </tr>
-            <tr>
-                <td>Eve</td>
-                <td>Jackson</td>
-            </tr>
-            <tr>
-                <td>John</td>
-                <td>Doe</td>
-            </tr>
+            <tbody>
+                <tr>
+                    <th>Key</th>
+                    <th>Fields</th>
+                </tr>
+                {this.createTable()}
+            </tbody>
         </table>)
     }
 }
\ No newline at end of file
diff --git a/src/fields/KVPField b/src/fields/KVPField
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/fields/KVPField.ts b/src/fields/KVPField.ts
new file mode 100644
index 000000000..a7ecc0768
--- /dev/null
+++ b/src/fields/KVPField.ts
@@ -0,0 +1,30 @@
+import { BasicField } from "./BasicField"
+import { FieldId } from "./Field";
+import { Types } from "../server/Message";
+import { Document } from "./Document"
+
+export class KVPField extends BasicField<Document> {
+    constructor(data: Document | undefined = undefined, id?: FieldId, save: boolean = true) {
+        super(data == undefined ? new Document() : data, save, id);
+    }
+
+    toString(): string {
+        return this.Data.Title;
+    }
+
+    ToScriptString(): string {
+        return `new KVPField("${this.Data}")`;
+    }
+
+    Copy() {
+        return new KVPField(this.Data);
+    }
+
+    ToJson(): { type: Types, data: Document, _id: string } {
+        return {
+            type: Types.Text,
+            data: this.Data,
+            _id: this.Id
+        }
+    }
+}
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 4a42946b5c8ec86e66a89fec2e66971a242e3dbb Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 28 Feb 2019 09:19:53 -0500
Subject: added css

---
 .vscode/launch.json                                |  4 -
 src/client/documents/Documents.ts                  |  4 +-
 .../views/collections/CollectionFreeFormView.tsx   |  5 +-
 src/client/views/nodes/DocumentView.tsx            |  4 +-
 src/client/views/nodes/FieldView.tsx               |  2 -
 src/client/views/nodes/KeyValueBox.scss            | 24 ++++++
 src/client/views/nodes/KeyValueBox.tsx             | 89 ++++++++++++++++++++
 src/client/views/nodes/KeyValuePair.tsx            |  6 +-
 src/client/views/nodes/KeyValuePane.scss           |  0
 src/client/views/nodes/KeyValuePane.tsx            | 96 ----------------------
 tsconfig.json                                      |  6 +-
 11 files changed, 124 insertions(+), 116 deletions(-)
 create mode 100644 src/client/views/nodes/KeyValueBox.scss
 create mode 100644 src/client/views/nodes/KeyValueBox.tsx
 delete mode 100644 src/client/views/nodes/KeyValuePane.scss
 delete mode 100644 src/client/views/nodes/KeyValuePane.tsx

(limited to 'src/client/views/collections/CollectionFreeFormView.tsx')

diff --git a/.vscode/launch.json b/.vscode/launch.json
index 8aa197fa5..074f9ddf0 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -12,10 +12,6 @@
             "breakOnLoad": true,
             "url": "http://localhost:1050",
             "webRoot": "${workspaceFolder}",
-            "skipFiles": [
-                "${workspaceRoot}/node_modules/**/*.js",
-                "${workspaceRoot}/node_modules/**/*.ts",
-            ]
         },
         {
             "type": "node",
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 41f1c9b3f..1d24ff7d2 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -13,7 +13,7 @@ import { CollectionView, CollectionViewType } from "../views/collections/Collect
 import { HtmlField } from "../../fields/HtmlField";
 import { Key } from "../../fields/Key"
 import { Field } from "../../fields/Field";
-import { KeyValuePane } from "../views/nodes/KeyValuePane"
+import { KeyValueBox } from "../views/nodes/KeyValueBox"
 import { KVPField } from "../../fields/KVPField";
 
 export interface DocumentOptions {
@@ -105,7 +105,7 @@ export namespace Documents {
 
     function GetKVPPrototype(): Document {
         return kvpProto ? kvpProto :
-            kvpProto = setupPrototypeOptions(kvpProtoId, "KVP_PROTO", KeyValuePane.LayoutString(),
+            kvpProto = setupPrototypeOptions(kvpProtoId, "KVP_PROTO", KeyValueBox.LayoutString(),
                 { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] })
     }
 
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 137bcf706..96b6d1477 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -16,6 +16,7 @@ import { DocumentView } from "../nodes/DocumentView";
 import { FormattedTextBox } from "../nodes/FormattedTextBox";
 import { ImageBox } from "../nodes/ImageBox";
 import { WebBox } from "../nodes/WebBox";
+import { KeyValueBox } from "../nodes/KeyValueBox"
 import "./CollectionFreeFormView.scss";
 import { COLLECTION_BORDER_WIDTH } from "./CollectionView";
 import { CollectionViewBase } from "./CollectionViewBase";
@@ -230,7 +231,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
     get backgroundView() {
         return !this.backgroundLayout ? (null) :
             (<JsxParser
-                components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox }}
+                components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValueBox }}
                 bindings={this.props.bindings}
                 jsx={this.backgroundLayout}
                 showWarnings={true}
@@ -241,7 +242,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
     get overlayView() {
         return !this.overlayLayout ? (null) :
             (<JsxParser
-                components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox }}
+                components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValueBox }}
                 bindings={this.props.bindings}
                 jsx={this.overlayLayout}
                 showWarnings={true}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 23cfa6df3..a02fde133 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -16,7 +16,7 @@ import { ContextMenu } from "../ContextMenu";
 import { FormattedTextBox } from "../nodes/FormattedTextBox";
 import { ImageBox } from "../nodes/ImageBox";
 import { Documents } from "../../documents/Documents"
-import { KeyValuePane } from "../nodes/KeyValuePane"
+import { KeyValueBox } from "./KeyValueBox"
 import { WebBox } from "../nodes/WebBox";
 import "./DocumentView.scss";
 import React = require("react");
@@ -205,7 +205,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
 
     @computed get mainContent() {
         return <JsxParser
-            components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValuePane }}
+            components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValueBox }}
             bindings={this._documentBindings}
             jsx={this.layout}
             showWarnings={true}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 056f834d1..f372258f8 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -12,8 +12,6 @@ import { Key } from "../../../fields/Key";
 import { FormattedTextBox } from "./FormattedTextBox";
 import { ImageBox } from "./ImageBox";
 import { WebBox } from "./WebBox";
-import { KVPField } from "../../../fields/KVPField";
-import { KeyValuePane } from "./KeyValuePane";
 
 //
 // these properties get assigned through the render() method of the DocumentView when it creates this node.
diff --git a/src/client/views/nodes/KeyValueBox.scss b/src/client/views/nodes/KeyValueBox.scss
new file mode 100644
index 000000000..f22989735
--- /dev/null
+++ b/src/client/views/nodes/KeyValueBox.scss
@@ -0,0 +1,24 @@
+.keyValueBox-cont {
+    overflow-y:scroll;
+    height: 100%;
+    border: black;
+    border-width: 1px;
+    border-style: solid;
+    box-sizing: border-box;
+    display: inline-block;
+}
+.keyValueBox-header {
+    background:gray;
+}
+.keyValueBox-evenRow {
+    background: white;
+    .formattedTextBox-cont {
+        background: white;
+    }
+}
+.keyValueBox-oddRow {
+    background: lightGray;
+    .formattedTextBox-cont {
+        background: lightgray;
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
new file mode 100644
index 000000000..7e2426b58
--- /dev/null
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -0,0 +1,89 @@
+
+import { IReactionDisposer } from 'mobx';
+import { observer } from "mobx-react";
+import { EditorView } from 'prosemirror-view';
+import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app
+import { Document } from '../../../fields/Document';
+import { Opt } from '../../../fields/Field';
+import { KeyStore } from '../../../fields/KeyStore';
+import { FieldView, FieldViewProps } from './FieldView';
+import { KeyValuePair } from "./KeyValuePair";
+import "./KeyValueBox.scss";
+import React = require("react")
+
+@observer
+export class KeyValueBox extends React.Component<FieldViewProps> {
+
+    public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(KeyValueBox, fieldStr) }
+    private _ref: React.RefObject<HTMLDivElement>;
+    private _editorView: Opt<EditorView>;
+    private _reactionDisposer: Opt<IReactionDisposer>;
+
+
+    constructor(props: FieldViewProps) {
+        super(props);
+
+        this._ref = React.createRef();
+    }
+
+
+
+    shouldComponentUpdate() {
+        return false;
+    }
+
+
+    onPointerDown = (e: React.PointerEvent): void => {
+        if (e.buttons === 1 && this.props.isSelected()) {
+            e.stopPropagation();
+        }
+    }
+    onPointerWheel = (e: React.WheelEvent): void => {
+        e.stopPropagation();
+    }
+
+    createTable = () => {
+        let table: Array<JSX.Element> = []
+        let ret = "waiting"
+        let doc = this.props.doc.GetT(KeyStore.Data, Document);
+        if (!doc || doc == "<Waiting>") {
+            return <tr><td>Loading...</td></tr>
+        }
+        let realDoc = doc;
+
+        let ids: { [key: string]: string } = {};
+        let protos = doc.GetAllPrototypes();
+        for (const proto of protos) {
+            proto._proxies.forEach((val, key) => {
+                if (!(key in ids)) {
+                    ids[key] = key;
+                }
+            })
+        }
+
+        let rows: JSX.Element[] = [];
+        let i = 0;
+        for (let key in ids) {
+            if (i++ % 2 == 0)
+                rows.push(<KeyValuePair doc={realDoc} rowStyle="keyValueBox-evenRow" fieldId={key} />)
+            else rows.push(<KeyValuePair doc={realDoc} rowStyle="keyValueBox-oddRow" fieldId={key} />)
+        }
+        return rows;
+    }
+
+
+    render() {
+
+        return (<div className="keyValueBox-cont">
+            <table className="keyValueBox-table">
+                <tbody>
+                    <tr className="keyValueBox-header">
+                        <th>Key</th>
+                        <th>Fields</th>
+                    </tr>
+                    {this.createTable()}
+                </tbody>
+            </table>
+        </div>)
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index b8a0cca48..ecdd47a1e 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -1,5 +1,5 @@
 import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app
-import "./KeyValuePane.scss";
+import "./KeyValueBox.scss";
 import React = require("react")
 import { FieldViewProps, FieldView } from './FieldView';
 import { Opt, Field } from '../../../fields/Field';
@@ -12,6 +12,7 @@ import { Server } from "../../Server"
 // Represents one row in a key value plane
 
 export interface KeyValuePairProps {
+    rowStyle: string;
     fieldId: string;
     doc: Document;
 }
@@ -33,7 +34,6 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
     }
 
 
-
     render() {
         if (!this.key) {
             return <tr><td>error</td><td></td></tr>
@@ -49,7 +49,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
             selectOnLoad: false,
         }
         return (
-            <tr><td>{this.key.Name}</td><td><FieldView {...props} /></td></tr>
+            <tr className={this.props.rowStyle}><td>{this.key.Name}</td><td><FieldView {...props} /></td></tr>
         )
     }
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/KeyValuePane.scss b/src/client/views/nodes/KeyValuePane.scss
deleted file mode 100644
index e69de29bb..000000000
diff --git a/src/client/views/nodes/KeyValuePane.tsx b/src/client/views/nodes/KeyValuePane.tsx
deleted file mode 100644
index 90f5b653c..000000000
--- a/src/client/views/nodes/KeyValuePane.tsx
+++ /dev/null
@@ -1,96 +0,0 @@
-
-import Lightbox from 'react-image-lightbox';
-import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app
-import "./KeyValuePane.scss";
-import React = require("react")
-import { FieldViewProps, FieldView } from './FieldView';
-import { FieldWaiting, Opt, Field } from '../../../fields/Field';
-import { observer } from "mobx-react"
-import { observable, action, IReactionDisposer, reaction, ObservableMap } from 'mobx';
-import { KeyStore } from '../../../fields/KeyStore';
-import { RichTextField } from "../../../fields/RichTextField";
-import { element } from 'prop-types';
-import { props } from 'bluebird';
-import { EditorView } from 'prosemirror-view';
-import { Transaction, EditorState } from 'prosemirror-state';
-import { schema } from 'prosemirror-schema-basic';
-import { keymap } from 'prosemirror-keymap';
-import { undo, redo } from 'prosemirror-history';
-import { baseKeymap } from 'prosemirror-commands';
-import { KVPField } from '../../../fields/KVPField';
-import { Document } from '../../../fields/Document';
-import { Key } from '../../../fields/Key';
-import { JSXElement } from 'babel-types';
-import { KeyValuePair } from "./KeyValuePair"
-
-@observer
-export class KeyValuePane extends React.Component<FieldViewProps> {
-
-    public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(KeyValuePane, fieldStr) }
-    private _ref: React.RefObject<HTMLDivElement>;
-    private _editorView: Opt<EditorView>;
-    private _reactionDisposer: Opt<IReactionDisposer>;
-
-
-    constructor(props: FieldViewProps) {
-        super(props);
-
-        this._ref = React.createRef();
-    }
-
-
-
-    shouldComponentUpdate() {
-        return false;
-    }
-
-
-    onPointerDown = (e: React.PointerEvent): void => {
-        if (e.buttons === 1 && this.props.isSelected()) {
-            e.stopPropagation();
-        }
-    }
-    onPointerWheel = (e: React.WheelEvent): void => {
-        e.stopPropagation();
-    }
-
-    createTable = () => {
-        let table: Array<JSX.Element> = []
-        let ret = "waiting"
-        let doc = this.props.doc.GetT(KeyStore.Data, Document);
-        if (!doc || doc == "<Waiting>") {
-            return <tr><td>Loading...</td></tr>
-        }
-        let realDoc = doc;
-
-        let ids: { [key: string]: string } = {};
-        let protos = doc.GetAllPrototypes();
-        for (const proto of protos) {
-            proto._proxies.forEach((val, key) => {
-                if (!(key in ids)) {
-                    ids[key] = key;
-                }
-            })
-        }
-
-        let rows: JSX.Element[] = [];
-        for (let key in ids) {
-            rows.push(<KeyValuePair doc={realDoc} fieldId={key} />)
-        }
-        return rows;
-    }
-
-
-    render() {
-
-        return (<table>
-            <tbody>
-                <tr>
-                    <th>Key</th>
-                    <th>Fields</th>
-                </tr>
-                {this.createTable()}
-            </tbody>
-        </table>)
-    }
-}
\ No newline at end of file
diff --git a/tsconfig.json b/tsconfig.json
index 823fc2732..e2538bc39 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -11,9 +11,5 @@
       "dom",
       "es2015"
     ]
-  },
-  "exclude": [
-    "node_modules",
-    "static"
-  ]
+  }
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2

