From 9047fbe7dc69572bd8178bc29616ed2c855933ce Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Mon, 13 May 2019 00:37:03 -0400
Subject: fixed putting link info on protoype. making images and videos show up
 reasonably in schema and kvp.  dragging of docs from schema.

---
 .../views/collections/CollectionSchemaView.tsx     | 32 +++++++++++-----------
 1 file changed, 16 insertions(+), 16 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 18319dc77..4984e26d1 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -24,6 +24,7 @@ import { Cast, FieldValue, NumCast } from "../../../new_fields/Types";
 import { listSpec } from "../../../new_fields/Schema";
 import { List } from "../../../new_fields/List";
 import { Id } from "../../../new_fields/RefField";
+import { isUndefined } from "typescript-collections/dist/lib/util";
 
 
 // bcz: need to add drag and drop of rows and columns.  This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
@@ -77,23 +78,22 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             PanelHeight: returnZero,
             PanelWidth: returnZero,
         };
-        let contents = (
-            <FieldView {...props} />
-        );
+        let fieldContentView = <FieldView {...props} />;
         let reference = React.createRef<HTMLDivElement>();
-        let onItemDown = SetupDrag(reference, () => props.Document, this.props.moveDocument);
+        let onItemDown = (e: React.PointerEvent) =>
+            (this.props.CollectionView!.props.isSelected() ?
+                SetupDrag(reference, () => props.Document, this.props.moveDocument)(e) : undefined);
         let applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => {
             const res = run({ this: doc });
             if (!res.success) return false;
-            const field = res.result;
-            doc[props.fieldKey] = field;
+            doc[props.fieldKey] = res.result;
             return true;
         };
         return (
             <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} key={props.Document[Id]} ref={reference}>
                 <EditableView
                     display={"inline"}
-                    contents={contents}
+                    contents={fieldContentView}
                     height={Number(MAX_ROW_HEIGHT)}
                     GetValue={() => {
                         let field = props.Document[props.fieldKey];
@@ -224,10 +224,11 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         this.previewScript = e.currentTarget.value;
     }
 
+    @computed
     get previewDocument(): Doc | undefined {
-        const children = Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []);
+        const children = DocListCast(this.props.Document[this.props.fieldKey]);
         const selected = children.length > this._selectedIndex ? FieldValue(children[this._selectedIndex]) : undefined;
-        return selected ? (this.previewScript ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined;
+        return selected ? (this.previewScript && this.previewScript != "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined;
     }
     get tableWidth() { return (this.props.PanelWidth() - 2 * this.borderWidth - this.DIVIDER_WIDTH) * (1 - this.splitPercentage / 100); }
     get previewRegionHeight() { return this.props.PanelHeight() - 2 * this.borderWidth; }
@@ -253,8 +254,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     get previewPanel() {
         // let doc = CompileScript(this.previewScript, { this: selected }, true)();
         const previewDoc = this.previewDocument;
-        return !previewDoc || !this.previewRegionWidth ? (null) : (
-            <div className="collectionSchemaView-previewRegion" style={{ width: `${this.previewRegionWidth}px` }}>
+        return (<div className="collectionSchemaView-previewRegion" style={{ width: `${this.previewRegionWidth}px` }}>
+            {!previewDoc || !this.previewRegionWidth ? (null) : (
                 <div className="collectionSchemaView-previewDoc" style={{ transform: `translate(${this.previewPanelCenteringOffset}px, 0px)` }}>
                     <DocumentView Document={previewDoc} isTopMost={false} selectOnLoad={false}
                         toggleMinimized={emptyFunction}
@@ -268,11 +269,10 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                         whenActiveChanged={this.props.whenActiveChanged}
                         bringToFront={emptyFunction}
                     />
-                </div>
-                <input className="collectionSchemaView-input" value={this.previewScript} onChange={this.onPreviewScriptChange}
-                    style={{ left: `calc(50% - ${Math.min(75, this.previewPanelWidth() / 2)}px)` }} />
-            </div>
-        );
+                </div>)}
+            <input className="collectionSchemaView-input" value={this.previewScript} onChange={this.onPreviewScriptChange}
+                style={{ left: `calc(50% - ${Math.min(75, (previewDoc ? this.previewPanelWidth() / 2 : 75))}px)` }} />
+        </div>);
     }
 
     get documentKeysCheckList() {
-- 
cgit v1.2.3-70-g09d2


From 3be42131bc08024f06e0daec8d09e45bf3f1ddab Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Mon, 13 May 2019 16:21:28 -0400
Subject: a bunch of fixes to schemas, marquees, and an experimental feature to
 set a document's data with linking UI

---
 src/client/util/DragManager.ts                             |  6 ++++--
 src/client/views/DocumentDecorations.tsx                   |  2 ++
 src/client/views/collections/CollectionDockingView.tsx     |  7 ++-----
 src/client/views/collections/CollectionSchemaView.tsx      |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx          |  4 ++--
 .../views/collections/collectionFreeForm/MarqueeView.tsx   |  8 +++-----
 src/client/views/nodes/DocumentContentsView.tsx            |  9 +++++++--
 src/client/views/nodes/DocumentView.tsx                    | 13 +++++++++++--
 src/client/views/nodes/ImageBox.tsx                        |  3 ++-
 src/client/views/nodes/KeyValueBox.tsx                     |  6 +++---
 src/client/views/nodes/LinkMenu.tsx                        |  2 +-
 src/client/views/nodes/PDFBox.tsx                          |  4 ++--
 src/new_fields/Doc.ts                                      | 14 +++++++++-----
 13 files changed, 49 insertions(+), 31 deletions(-)

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

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 2da0d5b51..26da34e67 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -105,7 +105,8 @@ export namespace DragManager {
         constructor(
             readonly x: number,
             readonly y: number,
-            readonly data: { [id: string]: any }
+            readonly data: { [id: string]: any },
+            readonly mods: string
         ) { }
     }
 
@@ -334,7 +335,8 @@ export namespace DragManager {
                     detail: {
                         x: e.x,
                         y: e.y,
-                        data: dragData
+                        data: dragData,
+                        mods: e.ctrlKey ? "Control" : ""
                     }
                 })
             );
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 4786b4de6..5aa3d804d 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -239,6 +239,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             this._removeIcon = snapped;
         }
     }
+    @undoBatch
     @action
     onMinimizeUp = (e: PointerEvent): void => {
         e.stopPropagation();
@@ -270,6 +271,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         runInAction(() => this._minimizedX = this._minimizedY = 0);
     }
 
+    @undoBatch
     @action createIcon = (selected: DocumentView[], layoutString: string): Doc => {
         let doc = selected[0].props.Document;
         let iconDoc = Docs.IconDocument(layoutString);
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 0aa067972..a755e0f91 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -5,7 +5,7 @@ import { observer } from "mobx-react";
 import * as ReactDOM from 'react-dom';
 import Measure from "react-measure";
 import * as GoldenLayout from "../../../client/goldenLayout";
-import { Doc, Field, Opt } from "../../../new_fields/Doc";
+import { Doc, Field, Opt, DocListCast } from "../../../new_fields/Doc";
 import { FieldId, Id } from "../../../new_fields/RefField";
 import { listSpec } from "../../../new_fields/Schema";
 import { Cast, NumCast, StrCast } from "../../../new_fields/Types";
@@ -313,10 +313,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                     counter.DashDocId = tab.contentItem.config.props.documentId;
                     tab.reactionDisposer = reaction(() => [doc.linkedFromDocs, doc.LinkedToDocs, doc.title],
                         () => {
-                            const lf = Cast(doc.linkedFromDocs, listSpec(Doc), []);
-                            const lt = Cast(doc.linkedToDocs, listSpec(Doc), []);
-                            let count = (lf ? lf.length : 0) + (lt ? lt.length : 0);
-                            counter.innerHTML = count;
+                            counter.innerHTML = DocListCast(doc.linkedFromDocs).length + DocListCast(doc.linkedToDocs).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/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 4984e26d1..9ecccc559 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -254,7 +254,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     get previewPanel() {
         // let doc = CompileScript(this.previewScript, { this: selected }, true)();
         const previewDoc = this.previewDocument;
-        return (<div className="collectionSchemaView-previewRegion" style={{ width: `${this.previewRegionWidth}px` }}>
+        return (<div className="collectionSchemaView-previewRegion" style={{ width: `${Math.max(0, this.previewRegionWidth - 1)}px` }}>
             {!previewDoc || !this.previewRegionWidth ? (null) : (
                 <div className="collectionSchemaView-previewDoc" style={{ transform: `translate(${this.previewPanelCenteringOffset}px, 0px)` }}>
                     <DocumentView Document={previewDoc} isTopMost={false} selectOnLoad={false}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index dc86f38b6..c36c708db 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -339,7 +339,7 @@ class CollectionFreeFormOverlayView extends React.Component<DocumentViewProps &
             isTopMost={this.props.isTopMost} isSelected={this.props.isSelected} select={emptyFunction} />);
     }
     render() {
-        return this.overlayView;
+        return this.props.Document.overlayLayout ? this.overlayView : (null);
     }
 }
 
@@ -350,7 +350,7 @@ class CollectionFreeFormBackgroundView extends React.Component<DocumentViewProps
             isTopMost={this.props.isTopMost} isSelected={this.props.isSelected} select={emptyFunction} />);
     }
     render() {
-        return this.backgroundView;
+        return this.props.Document.backgroundLayout ? this.backgroundView : (null);
     }
 }
 
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 1c29ebaae..24dea200e 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -104,10 +104,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                             continue;
                         }
                         let doc = new Doc();
-                        columns.forEach((col, i) => {
-                            console.log(values[i] + " " + Number(values[i]).toString());
-                            doc[columns[i]] = (values.length > i ? ((values[i].indexOf(Number(values[i]).toString()) !== -1) ? Number(values[i]) : values[i]) : undefined);
-                        });
+                        columns.forEach((col, i) => doc[columns[i]] = (values.length > i ? ((values[i].indexOf(Number(values[i]).toString()) !== -1) ? Number(values[i]) : values[i]) : undefined));
                         if (groupAttr) {
                             doc["_group"] = groupAttr;
                         }
@@ -207,7 +204,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
     @undoBatch
     @action
     marqueeCommand = async (e: KeyboardEvent) => {
-        if (this._commandExecuted) {
+        if (this._commandExecuted || (e as any).propagationIsStopped) {
             return;
         }
         if (e.key === "Backspace" || e.key === "Delete" || e.key === "d") {
@@ -224,6 +221,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
         if (e.key === "c" || e.key === "r" || e.key === "s" || e.key === "e" || e.key === "p") {
             this._commandExecuted = true;
             e.stopPropagation();
+            (e as any).propagationIsStopped = true;
             let bounds = this.Bounds;
             let selected = this.marqueeSelect().map(d => {
                 if (e.key === "s") {
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index f404b7bc6..3ddf8eb00 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -43,9 +43,14 @@ const ObserverJsxParser: typeof JsxParser = ObserverJsxParser1 as any;
 export class DocumentContentsView extends React.Component<DocumentViewProps & {
     isSelected: () => boolean,
     select: (ctrl: boolean) => void,
-    layoutKey: string
+    layoutKey: string,
 }> {
-    @computed get layout(): string { return Cast(this.props.Document[this.props.layoutKey], "string", this.props.layoutKey === "layout" ? "<p>Error loading layout data</p>" : ""); }
+    @computed get layout(): string {
+        return StrCast(this.props.Document[this.props.layoutKey],
+            this.props.Document.data ?
+                "<FieldView {...props} fieldKey='data' />" :
+                KeyValueBox.LayoutString(this.props.Document.proto ? "proto" : ""));
+    }
 
     CreateBindings(): JsxBindings {
         return { props: OmitKeys(this.props, ['parentActive'], (obj: any) => obj.active = this.props.parentActive).omit };
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index edc2158f0..b7ad9249a 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -243,8 +243,17 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
             const protoDest = destDoc.proto;
             const protoSrc = sourceDoc.proto;
-            Doc.MakeLink(protoSrc ? protoSrc : sourceDoc, protoDest ? protoDest : destDoc);
-            de.data.droppedDocuments.push(destDoc);
+            if (de.mods == "Control") {
+                let src = protoSrc ? protoSrc : sourceDoc;
+                let dst = protoDest ? protoDest : destDoc;
+                dst.data = src;
+                dst.nativeWidth = src.nativeWidth;
+                dst.nativeHeight = src.nativeHeight;
+            }
+            else {
+                Doc.MakeLink(protoSrc ? protoSrc : sourceDoc, protoDest ? protoDest : destDoc);
+                de.data.droppedDocuments.push(destDoc);
+            }
             e.stopPropagation();
         }
     }
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index f9659a4b2..05742f8d1 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -42,8 +42,9 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
     onLoad = (target: any) => {
         var h = this._imgRef.current!.naturalHeight;
         var w = this._imgRef.current!.naturalWidth;
+        console.log("title: " + this.Document.title);
         if (this._photoIndex === 0) {
-            this.Document.nativeHeight = FieldValue(this.Document.nativeWidth, 0) * h / w;
+            Doc.SetOnPrototype(this.Document, "nativeHeight", FieldValue(this.Document.nativeWidth, 0) * h / w);
             this.Document.height = FieldValue(this.Document.width, 0) * h / w;
         }
     }
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index 876a3c173..c9d665ceb 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -18,7 +18,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
     @observable private _keyInput: string = "";
     @observable private _valueInput: string = "";
     @computed get splitPercentage() { return NumCast(this.props.Document.schemaSplitPercentage, 50); }
-
+    get fieldDocToLayout() { return this.props.fieldKey ? FieldValue(Cast(this.props.Document[this.props.fieldKey], Doc)) : this.props.Document }
 
     constructor(props: FieldViewProps) {
         super(props);
@@ -28,7 +28,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
     onEnterKey = (e: React.KeyboardEvent): void => {
         if (e.key === 'Enter') {
             if (this._keyInput && this._valueInput) {
-                let doc = FieldValue(Cast(this.props.Document.data, Doc));
+                let doc = this.fieldDocToLayout;
                 if (!doc) {
                     return;
                 }
@@ -60,7 +60,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
     }
 
     createTable = () => {
-        let doc = FieldValue(Cast(this.props.Document.data, Doc));
+        let doc = this.fieldDocToLayout;
         if (!doc) {
             return <tr><td>Loading...</td></tr>;
         }
diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx
index 7bf13d5f9..5dabfc30d 100644
--- a/src/client/views/nodes/LinkMenu.tsx
+++ b/src/client/views/nodes/LinkMenu.tsx
@@ -32,7 +32,7 @@ export class LinkMenu extends React.Component<Props> {
     render() {
         //get list of links from document
         let linkFrom = DocListCast(this.props.docView.props.Document.linkedFromDocs);
-        let linkTo = DocListCast(this.props.docView.props.Document.linkedToDoc);
+        let linkTo = DocListCast(this.props.docView.props.Document.linkedToDocs);
         if (this._editingLink === undefined) {
             return (
                 <div id="linkMenu-container">
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index cb27b3f1b..ff8737192 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -1,5 +1,5 @@
 import * as htmlToImage from "html-to-image";
-import { action, computed, IReactionDisposer, observable, reaction, Reaction, trace } from 'mobx';
+import { action, computed, IReactionDisposer, observable, reaction, Reaction, trace, runInAction } from 'mobx';
 import { observer } from "mobx-react";
 import 'react-image-lightbox/style.css';
 import Measure from "react-measure";
@@ -223,7 +223,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
             document.addEventListener("pointerup", this.onPointerUp);
         }
         if (this.props.isSelected() && e.buttons === 2) {
-            this._alt = true;
+            runInAction(() => this._alt = true);
             document.removeEventListener("pointerup", this.onPointerUp);
             document.addEventListener("pointerup", this.onPointerUp);
         }
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index a8c9d28e1..4c837fcbd 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -173,11 +173,15 @@ export namespace Doc {
     export function MakeAlias(doc: Doc) {
         const alias = new Doc;
 
-        PromiseValue(Cast(doc.proto, Doc)).then(proto => {
-            if (proto) {
-                alias.proto = proto;
-            }
-        });
+        if (!doc.proto) {
+            alias.proto = doc;
+        } else {
+            PromiseValue(Cast(doc.proto, Doc)).then(proto => {
+                if (proto) {
+                    alias.proto = proto;
+                }
+            });
+        }
 
         return alias;
     }
-- 
cgit v1.2.3-70-g09d2


From 281bfa589bd1ca66823003ca91cc11ce895fe5e2 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 14 May 2019 18:59:32 -0400
Subject: fixes for northstar

---
 src/client/documents/Documents.ts                  |  9 ++-
 src/client/northstar/dash-fields/HistogramField.ts | 11 ++--
 .../dash-nodes/HistogramBinPrimitiveCollection.ts  |  4 +-
 src/client/northstar/dash-nodes/HistogramBox.tsx   | 16 +++---
 .../dash-nodes/HistogramBoxPrimitives.tsx          |  3 -
 src/client/northstar/manager/Gateway.ts            | 12 ++++
 src/client/northstar/model/ModelHelpers.ts         | 10 +++-
 src/client/northstar/model/idea/idea.ts            |  6 ++
 src/client/northstar/operations/BaseOperation.ts   | 17 ------
 .../northstar/operations/HistogramOperation.ts     | 12 ++--
 src/client/views/Main.tsx                          | 54 +-----------------
 .../views/collections/CollectionSchemaView.tsx     | 39 ++++++++++++-
 .../collections/collectionFreeForm/MarqueeView.tsx |  7 ++-
 src/client/views/nodes/DocumentView.tsx            |  2 +-
 .../authentication/models/current_user_utils.ts    | 65 ++++++++++++++++++++--
 15 files changed, 162 insertions(+), 105 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 11929455c..ed260d42e 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -33,6 +33,7 @@ import { DocServer } from "../DocServer";
 import { StrokeData, InkField } from "../../new_fields/InkField";
 import { dropActionType } from "../util/DragManager";
 import { DateField } from "../../new_fields/DateField";
+import { schema } from "prosemirror-schema-basic";
 
 export interface DocumentOptions {
     x?: number;
@@ -207,16 +208,18 @@ export namespace Docs {
     export function PdfDocument(url: string, options: DocumentOptions = {}) {
         return CreateInstance(pdfProto, new PdfField(new URL(url)), options);
     }
+
     export async function DBDocument(url: string, options: DocumentOptions = {}) {
         let schemaName = options.title ? options.title : "-no schema-";
         let ctlog = await Gateway.Instance.GetSchema(url, schemaName);
         if (ctlog && ctlog.schemas) {
             let schema = ctlog.schemas[0];
             let schemaDoc = Docs.TreeDocument([], { ...options, nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: schema.displayName! });
-            let schemaDocuments = Cast(schemaDoc.data, listSpec(Doc));
+            let schemaDocuments = Cast(schemaDoc.data, listSpec(Doc), []);
             if (!schemaDocuments) {
                 return;
             }
+            CurrentUserUtils.AddNorthstarSchema(schema, schemaDoc);
             const docs = schemaDocuments;
             CurrentUserUtils.GetAllNorthstarColumnAttributes(schema).map(attr => {
                 DocServer.GetRefField(attr.displayName! + ".alias").then(action((field: Opt<Field>) => {
@@ -251,8 +254,8 @@ export namespace Docs {
         }
         return CreateInstance(collProto, new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Freeform });
     }
-    export function SchemaDocument(documents: Array<Doc>, options: DocumentOptions) {
-        return CreateInstance(collProto, new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Schema });
+    export function SchemaDocument(schemaColumns: string[], documents: Array<Doc>, options: DocumentOptions) {
+        return CreateInstance(collProto, new List(documents), { schemaColumns: new List(schemaColumns), ...options, viewType: CollectionViewType.Schema });
     }
     export function TreeDocument(documents: Array<Doc>, options: DocumentOptions) {
         return CreateInstance(collProto, new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Tree });
diff --git a/src/client/northstar/dash-fields/HistogramField.ts b/src/client/northstar/dash-fields/HistogramField.ts
index f01f08487..aabc77bb2 100644
--- a/src/client/northstar/dash-fields/HistogramField.ts
+++ b/src/client/northstar/dash-fields/HistogramField.ts
@@ -9,7 +9,8 @@ import { OmitKeys } from "../../../Utils";
 import { Deserializable } from "../../util/SerializationHelper";
 
 function serialize(field: HistogramField) {
-    return OmitKeys(field.HistoOp, ['Links', 'BrushLinks', 'Result', 'BrushColors', 'FilterModels', 'FilterOperand']).omit;
+    let obj = OmitKeys(field, ['Links', 'BrushLinks', 'Result', 'BrushColors', 'FilterModels', 'FilterOperand']).omit;
+    return obj;
 }
 
 function deserialize(jp: any) {
@@ -31,10 +32,10 @@ function deserialize(jp: any) {
             }
         });
         if (X && Y && V) {
-            return new HistogramField(new HistogramOperation(jp.SchemaName, X, Y, V, jp.Normalization));
+            return new HistogramOperation(jp.SchemaName, X, Y, V, jp.Normalization);
         }
     }
-    return new HistogramField(HistogramOperation.Empty);
+    return HistogramOperation.Empty;
 }
 
 @Deserializable("histogramField")
@@ -50,6 +51,8 @@ export class HistogramField extends ObjectField {
     }
 
     [Copy]() {
-        return new HistogramField(this.HistoOp.Copy());
+        let y = this.HistoOp;
+        let z = this.HistoOp["Copy"];
+        return new HistogramField(HistogramOperation.Duplicate(this.HistoOp));
     }
 }
\ No newline at end of file
diff --git a/src/client/northstar/dash-nodes/HistogramBinPrimitiveCollection.ts b/src/client/northstar/dash-nodes/HistogramBinPrimitiveCollection.ts
index 6291ec1fc..3e9145a1b 100644
--- a/src/client/northstar/dash-nodes/HistogramBinPrimitiveCollection.ts
+++ b/src/client/northstar/dash-nodes/HistogramBinPrimitiveCollection.ts
@@ -198,8 +198,8 @@ export class HistogramBinPrimitiveCollection {
         var marginParams = new MarginAggregateParameters();
         marginParams.aggregateFunction = axis.AggregateFunction;
         var marginAggregateKey = ModelHelpers.CreateAggregateKey(this.histoOp.Schema!.distinctAttributeParameters, axis, this.histoResult, brush.brushIndex!, marginParams);
-        var marginResult = ModelHelpers.GetAggregateResult(bin, marginAggregateKey) as MarginAggregateResult;
-        return !marginResult ? 0 : marginResult.absolutMargin!;
+        let aggResult = ModelHelpers.GetAggregateResult(bin, marginAggregateKey);
+        return aggResult instanceof MarginAggregateResult && aggResult.absolutMargin ? aggResult.absolutMargin : 0;
     }
 
     private createBinPrimitive(barAxis: number, brush: Brush, marginRect: PIXIRectangle,
diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx
index ed556cf45..eb1ad69b7 100644
--- a/src/client/northstar/dash-nodes/HistogramBox.tsx
+++ b/src/client/northstar/dash-nodes/HistogramBox.tsx
@@ -17,9 +17,8 @@ import "./HistogramBox.scss";
 import { HistogramBoxPrimitives } from './HistogramBoxPrimitives';
 import { HistogramLabelPrimitives } from "./HistogramLabelPrimitives";
 import { StyleConstants } from "../utils/StyleContants";
-import { NumCast, Cast } from "../../../new_fields/Types";
-import { listSpec } from "../../../new_fields/Schema";
-import { Doc, DocListCast } from "../../../new_fields/Doc";
+import { Cast } from "../../../new_fields/Types";
+import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc";
 import { Id } from "../../../new_fields/RefField";
 
 
@@ -119,15 +118,16 @@ export class HistogramBox extends React.Component<FieldViewProps> {
                 if (this.HistoOp !== HistogramOperation.Empty) {
                     reaction(() => DocListCast(this.props.Document.linkedFromDocs), (docs) => this.HistoOp.Links.splice(0, this.HistoOp.Links.length, ...docs), { fireImmediately: true });
                     reaction(() => DocListCast(this.props.Document.brushingDocs).length,
-                        () => {
-                            let brushingDocs = DocListCast(this.props.Document.brushingDocs);
+                        async () => {
+                            let brushingDocs = await DocListCastAsync(this.props.Document.brushingDocs);
                             const proto = this.props.Document.proto;
-                            if (proto) {
-                                this.HistoOp.BrushLinks.splice(0, this.HistoOp.BrushLinks.length, ...brushingDocs.map((brush, i) => {
+                            if (proto && brushingDocs) {
+                                let mapped = brushingDocs.map((brush, i) => {
                                     brush.backgroundColor = StyleConstants.BRUSH_COLORS[i % StyleConstants.BRUSH_COLORS.length];
                                     let brushed = DocListCast(brush.brushingDocs);
                                     return { l: brush, b: brushed[0][Id] === proto[Id] ? brushed[1] : brushed[0] };
-                                }));
+                                });
+                                this.HistoOp.BrushLinks.splice(0, this.HistoOp.BrushLinks.length, ...mapped);
                             }
                         }, { fireImmediately: true });
                     reaction(() => this.createOperationParamsCache, () => this.HistoOp.Update(), { fireImmediately: true });
diff --git a/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx b/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx
index 721bf6a89..350987695 100644
--- a/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx
+++ b/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx
@@ -11,9 +11,6 @@ import { StyleConstants } from "../../northstar/utils/StyleContants";
 import { HistogramBinPrimitiveCollection, HistogramBinPrimitive } from "./HistogramBinPrimitiveCollection";
 import { HistogramBox } from "./HistogramBox";
 import "./HistogramBoxPrimitives.scss";
-import { JSXElement } from "babel-types";
-import { Utils } from "../utils/Utils";
-import { all } from "bluebird";
 
 export interface HistogramPrimitivesProps {
     HistoBox: HistogramBox;
diff --git a/src/client/northstar/manager/Gateway.ts b/src/client/northstar/manager/Gateway.ts
index d26f2724f..c541cce6a 100644
--- a/src/client/northstar/manager/Gateway.ts
+++ b/src/client/northstar/manager/Gateway.ts
@@ -23,6 +23,18 @@ export class Gateway {
         }
     }
 
+    public async PostSchema(csvdata: string, schemaname: string): Promise<string> {
+        try {
+            const json = await this.MakePostJsonRequest("postSchema", { csv: csvdata, schema: schemaname });
+            // const cat = Catalog.fromJS(json);
+            // return cat;
+            return json;
+        }
+        catch (error) {
+            throw new Error("can not reach northstar's backend");
+        }
+    }
+
     public async GetSchema(pathname: string, schemaname: string): Promise<Catalog> {
         try {
             const json = await this.MakeGetRequest("schema", undefined, { path: pathname, schema: schemaname });
diff --git a/src/client/northstar/model/ModelHelpers.ts b/src/client/northstar/model/ModelHelpers.ts
index ac807b41f..80bb71224 100644
--- a/src/client/northstar/model/ModelHelpers.ts
+++ b/src/client/northstar/model/ModelHelpers.ts
@@ -31,7 +31,15 @@ export class ModelHelpers {
     }
 
     public static GetAggregateParametersIndex(histogramResult: HistogramResult, aggParameters?: AggregateParameters): number {
-        return ArrayUtil.IndexOfWithEqual(histogramResult.aggregateParameters!, aggParameters);
+        return Array.from(histogramResult.aggregateParameters!).findIndex((value, i, set) => {
+            if (set[i] instanceof CountAggregateParameters && value instanceof CountAggregateParameters)
+                return true;
+            if (set[i] instanceof MarginAggregateParameters && value instanceof MarginAggregateParameters)
+                return true;
+            if (set[i] instanceof SumAggregateParameters && value instanceof SumAggregateParameters)
+                return true;
+            return false;
+        });
     }
 
     public static GetAggregateParameter(distinctAttributeParameters: AttributeParameters | undefined, atm: AttributeTransformationModel): AggregateParameters | undefined {
diff --git a/src/client/northstar/model/idea/idea.ts b/src/client/northstar/model/idea/idea.ts
index 9d9d60678..c73a822c7 100644
--- a/src/client/northstar/model/idea/idea.ts
+++ b/src/client/northstar/model/idea/idea.ts
@@ -22,6 +22,9 @@ export abstract class AggregateParameters implements IAggregateParameters {
 
     protected _discriminator: string;
 
+    public Equals(other: Object): boolean {
+        return this == other;
+    }
     constructor(data?: IAggregateParameters) {
         if (data) {
             for (var property in data) {
@@ -204,6 +207,9 @@ export interface IAverageAggregateParameters extends ISingleDimensionAggregatePa
 export abstract class AttributeParameters implements IAttributeParameters {
     visualizationHints?: VisualizationHint[] | undefined;
     rawName?: string | undefined;
+    public Equals(other: Object): boolean {
+        return this == other;
+    }
 
     protected _discriminator: string;
 
diff --git a/src/client/northstar/operations/BaseOperation.ts b/src/client/northstar/operations/BaseOperation.ts
index c6d5f0a15..0d1361ebf 100644
--- a/src/client/northstar/operations/BaseOperation.ts
+++ b/src/client/northstar/operations/BaseOperation.ts
@@ -25,23 +25,6 @@ export abstract class BaseOperation {
 
     @computed
     public get FilterString(): string {
-
-        // let filterModels: FilterModel[] = [];
-        // return FilterModel.GetFilterModelsRecursive(this, new Set<GraphNode<BaseOperationViewModel, FilterLinkViewModel>>(), filterModels, true)
-        // if (this.OverridingFilters.length > 0) {
-        //     return "(" + this.OverridingFilters.filter(fm => fm !== null).map(fm => fm.ToPythonString()).join(" || ") + ")";
-        // }
-        // let rdg = MainManager.Instance.MainViewModel.FilterReverseDependencyGraph;
-        // let sliceModel = this.TypedViewModel.IncomingSliceModel;
-        // if (sliceModel !== null && sliceModel.Source !== null && instanceOfIBaseFilterProvider(sliceModel.Source) && rdg.has(sliceModel.Source)) {
-        //     let filterModels = sliceModel.Source.FilterModels.map(f => f);
-        //     return FilterModel.GetFilterModelsRecursive(rdg.get(sliceModel.Source), new Set<GraphNode<BaseOperationViewModel, FilterLinkViewModel>>(), filterModels, false);
-        // }
-
-        // if (rdg.has(this.TypedViewModel)) {
-        //     let filterModels = [];
-        //     return FilterModel.GetFilterModelsRecursive(rdg.get(this.TypedViewModel), new Set<GraphNode<BaseOperationViewModel, FilterLinkViewModel>>(), filterModels, true)
-        // }
         return "";
     }
 
diff --git a/src/client/northstar/operations/HistogramOperation.ts b/src/client/northstar/operations/HistogramOperation.ts
index 78b206bdc..74e23ea48 100644
--- a/src/client/northstar/operations/HistogramOperation.ts
+++ b/src/client/northstar/operations/HistogramOperation.ts
@@ -30,7 +30,7 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons
     @observable public V: AttributeTransformationModel;
     @observable public SchemaName: string;
     @observable public QRange: QuantitativeBinRange | undefined;
-    @computed public get Schema() { return CurrentUserUtils.GetNorthstarSchema(this.SchemaName); }
+    public get Schema() { return CurrentUserUtils.GetNorthstarSchema(this.SchemaName); }
 
     constructor(schemaName: string, x: AttributeTransformationModel, y: AttributeTransformationModel, v: AttributeTransformationModel, normalized?: number) {
         super();
@@ -41,7 +41,11 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons
         this.SchemaName = schemaName;
     }
 
-    Copy(): HistogramOperation {
+    public static Duplicate(op: HistogramOperation) {
+
+        return new HistogramOperation(op.SchemaName, op.X, op.Y, op.V, op.Normalization);
+    }
+    public Copy(): HistogramOperation {
         return new HistogramOperation(this.SchemaName, this.X, this.Y, this.V, this.Normalization);
     }
 
@@ -50,7 +54,7 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons
     }
 
 
-    @computed public get FilterModels() {
+    public get FilterModels() {
         return this.BarFilterModels;
     }
     @action
@@ -71,9 +75,7 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons
         return FilterModel.GetFilterModelsRecursive(this, new Set<IBaseFilterProvider>(), filterModels, true);
     }
 
-    @computed
     public get BrushString(): string[] {
-        trace();
         let brushes: string[] = [];
         this.BrushLinks.map(brushLink => {
             let brushHistogram = Cast(brushLink.b.data, HistogramField);
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 66205f8ca..385fc6ead 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -12,13 +12,6 @@ import { CurrentUserUtils } from '../../server/authentication/models/current_use
 import { RouteStore } from '../../server/RouteStore';
 import { emptyFunction, returnTrue, Utils, returnOne, returnZero } from '../../Utils';
 import { Docs } from '../documents/Documents';
-import { ColumnAttributeModel } from '../northstar/core/attribute/AttributeModel';
-import { AttributeTransformationModel } from '../northstar/core/attribute/AttributeTransformationModel';
-import { Gateway, NorthstarSettings } from '../northstar/manager/Gateway';
-import { AggregateFunction, Catalog } from '../northstar/model/idea/idea';
-import '../northstar/model/ModelExtensions';
-import { HistogramOperation } from '../northstar/operations/HistogramOperation';
-import '../northstar/utils/Extensions';
 import { SetupDrag, DragManager } from '../util/DragManager';
 import { Transform } from '../util/Transform';
 import { UndoManager } from '../util/UndoManager';
@@ -70,8 +63,6 @@ export class Main extends React.Component {
             }
         }
 
-        CurrentUserUtils.loadCurrentUser();
-
         library.add(faFont);
         library.add(faImage);
         library.add(faFilePdf);
@@ -84,15 +75,8 @@ export class Main extends React.Component {
         library.add(faFilm);
         library.add(faMusic);
         library.add(faTree);
-
         this.initEventListeners();
         this.initAuthenticationRouters();
-
-        // try {
-        //     this.initializeNorthstar();
-        // } catch (e) {
-
-        // }
     }
 
     componentDidMount() { window.onpopstate = this.onHistory; }
@@ -155,7 +139,7 @@ export class Main extends React.Component {
             // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
             setTimeout(() => {
                 this.openWorkspace(mainDoc);
-                let pendingDocument = Docs.SchemaDocument([], { title: "New Mobile Uploads" });
+                let pendingDocument = Docs.SchemaDocument(["title"], [], { title: "New Mobile Uploads" });
                 mainDoc.optionalRightCollection = pendingDocument;
             }, 0);
         }
@@ -229,7 +213,7 @@ export class Main extends React.Component {
 
         let addTextNode = action(() => Docs.TextDocument({ borderRounding: -1, width: 200, height: 200, title: "a text note" }));
         let addColNode = action(() => Docs.FreeformDocument([], { width: 200, height: 200, title: "a freeform collection" }));
-        let addSchemaNode = action(() => Docs.SchemaDocument([], { width: 200, height: 200, title: "a schema collection" }));
+        let addSchemaNode = action(() => Docs.SchemaDocument(["title"], [], { width: 200, height: 200, title: "a schema collection" }));
         let addTreeNode = action(() => Docs.TreeDocument([CurrentUserUtils.UserDocument], { width: 250, height: 400, title: "Library:" + CurrentUserUtils.email, dropAction: "alias" }));
         // let addTreeNode = action(() => Docs.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", dropAction: "copy"  }));
         let addVideoNode = action(() => Docs.VideoDocument(videourl, { width: 200, title: "video node" }));
@@ -300,40 +284,6 @@ export class Main extends React.Component {
             </div>
         );
     }
-
-    // --------------- Northstar hooks ------------- /
-    private _northstarSchemas: Doc[] = [];
-
-    @action SetNorthstarCatalog(ctlog: Catalog) {
-        CurrentUserUtils.NorthstarDBCatalog = ctlog;
-        if (ctlog && ctlog.schemas) {
-            ctlog.schemas.map(schema => {
-                let schemaDocuments: Doc[] = [];
-                let attributesToBecomeDocs = CurrentUserUtils.GetAllNorthstarColumnAttributes(schema);
-                Promise.all(attributesToBecomeDocs.reduce((promises, attr) => {
-                    promises.push(DocServer.GetRefField(attr.displayName! + ".alias").then(action((field: Opt<Field>) => {
-                        if (field instanceof Doc) {
-                            schemaDocuments.push(field);
-                        } else {
-                            var atmod = new ColumnAttributeModel(attr);
-                            let histoOp = new HistogramOperation(schema.displayName!,
-                                new AttributeTransformationModel(atmod, AggregateFunction.None),
-                                new AttributeTransformationModel(atmod, AggregateFunction.Count),
-                                new AttributeTransformationModel(atmod, AggregateFunction.Count));
-                            schemaDocuments.push(Docs.HistogramDocument(histoOp, { width: 200, height: 200, title: attr.displayName! }));
-                        }
-                    })));
-                    return promises;
-                }, [] as Promise<void>[])).finally(() =>
-                    this._northstarSchemas.push(Docs.TreeDocument(schemaDocuments, { width: 50, height: 100, title: schema.displayName! })));
-            });
-        }
-    }
-    async initializeNorthstar(): Promise<void> {
-        const getEnvironment = await fetch("/assets/env.json", { redirect: "follow", method: "GET", credentials: "include" });
-        NorthstarSettings.Instance.UpdateEnvironment(await getEnvironment.json());
-        Gateway.Instance.ClearCatalog().then(async () => this.SetNorthstarCatalog(await Gateway.Instance.GetCatalog()));
-    }
 }
 
 (async () => {
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 9ecccc559..f4ad5b357 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -20,11 +20,20 @@ import { FieldView, FieldViewProps } from "../nodes/FieldView";
 import "./CollectionSchemaView.scss";
 import { CollectionSubView } from "./CollectionSubView";
 import { Opt, Field, Doc, DocListCastAsync, DocListCast } from "../../../new_fields/Doc";
-import { Cast, FieldValue, NumCast } from "../../../new_fields/Types";
+import { Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types";
 import { listSpec } from "../../../new_fields/Schema";
 import { List } from "../../../new_fields/List";
 import { Id } from "../../../new_fields/RefField";
 import { isUndefined } from "typescript-collections/dist/lib/util";
+import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
+import { Gateway } from "../../northstar/manager/Gateway";
+import { DocServer } from "../../DocServer";
+import { ColumnAttributeModel } from "../../northstar/core/attribute/AttributeModel";
+import { HistogramOperation } from "../../northstar/operations/HistogramOperation";
+import { AggregateFunction } from "../../northstar/model/idea/idea";
+import { AttributeTransformationModel } from "../../northstar/core/attribute/AttributeTransformationModel";
+import { Docs } from "../../documents/Documents";
+import { ContextMenu } from "../ContextMenu";
 
 
 // bcz: need to add drag and drop of rows and columns.  This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
@@ -207,6 +216,32 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         }
     }
 
+    onContextMenu = (e: React.MouseEvent): void => {
+        if (!e.isPropagationStopped() && this.props.Document[Id] !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
+            ContextMenu.Instance.addItem({ description: "Make DB", event: this.makeDB });
+        }
+    }
+
+    @action
+    makeDB = async () => {
+        let csv: string = this.columns.reduce((val, col) => val + col + ",", "");
+        csv = csv.substr(0, csv.length - 1) + "\n";
+        let self = this;
+        DocListCast(this.props.Document.data).map(doc => {
+            csv += self.columns.reduce((val, col) => val + (doc[col] ? doc[col]!.toString() : "") + ",", "");
+            csv = csv.substr(0, csv.length - 1) + "\n";
+        })
+        csv.substring(0, csv.length - 1);
+        let dbName = StrCast(this.props.Document.title);
+        let res = await Gateway.Instance.PostSchema(csv, dbName);
+        if (self.props.CollectionView.props.addDocument) {
+            let schemaDoc = await Docs.DBDocument("https://www.cs.brown.edu/" + dbName, { title: dbName });
+            if (schemaDoc) {
+                self.props.CollectionView.props.addDocument(schemaDoc, false); 
+            }
+        }
+    }
+
     @action
     addColumn = () => {
         this.columns.push(this._newKeyName);
@@ -325,7 +360,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         const children = this.children;
         return (
             <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel}
-                onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createTarget}>
+                onDrop={(e: React.DragEvent) => this.onDrop(e, {})} onContextMenu={this.onContextMenu} ref={this.createTarget}>
                 <div className="collectionSchemaView-tableContainer" style={{ width: `${this.tableWidth}px` }}>
                     <ReactTable data={children} page={0} pageSize={children.length} showPagination={false}
                         columns={this.columns.map(col => ({
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 24dea200e..be7cddca6 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -17,6 +17,9 @@ import { InkField, StrokeData } from "../../../../new_fields/InkField";
 import { List } from "../../../../new_fields/List";
 import { ImageField } from "../../../../new_fields/URLField";
 import { Template, Templates } from "../../Templates";
+import { Gateway } from "../../../northstar/manager/Gateway";
+import { DocServer } from "../../../DocServer";
+import { Id } from "../../../../new_fields/RefField";
 
 interface MarqueeViewProps {
     getContainerTransform: () => Transform;
@@ -111,8 +114,8 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                         doc.title = i.toString();
                         docList.push(doc);
                     }
-                    let newCol = Docs.SchemaDocument(docList, { x: x, y: y, title: "-dropped table-", width: 300, height: 100 });
-                    newCol.proto!.schemaColumns = new List<string>([...(groupAttr ? ["_group"] : []), ...columns.filter(c => c)]);
+                    let newCol = Docs.SchemaDocument([...(groupAttr ? ["_group"] : []), ...columns.filter(c => c)], docList, { x: x, y: y, title: "droppedTable", width: 300, height: 100 });
+
                     this.props.addDocument(newCol, false);
                 }
             })();
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index b7ad9249a..c97bcbd94 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -306,7 +306,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         cm.addItem({
             description: "Find aliases", event: async () => {
                 const aliases = await SearchUtil.GetAliasesOfDocument(this.props.Document);
-                CollectionDockingView.Instance.AddRightSplit(Docs.SchemaDocument(aliases, {}));
+                CollectionDockingView.Instance.AddRightSplit(Docs.SchemaDocument(["title"], aliases, {}));
             }
         });
         cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(DocServer.prepend("/doc/" + this.props.Document[Id])) });
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index 5f45d7bcc..5b63ac356 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -1,15 +1,21 @@
 import { computed, observable, action, runInAction } from "mobx";
 import * as rp from 'request-promise';
 import { Docs } from "../../../client/documents/Documents";
-import { Attribute, AttributeGroup, Catalog, Schema } from "../../../client/northstar/model/idea/idea";
+import { Attribute, AttributeGroup, Catalog, Schema, AggregateFunction } from "../../../client/northstar/model/idea/idea";
 import { ArrayUtil } from "../../../client/northstar/utils/ArrayUtil";
 import { RouteStore } from "../../RouteStore";
 import { DocServer } from "../../../client/DocServer";
-import { Doc } from "../../../new_fields/Doc";
+import { Doc, Opt, Field } from "../../../new_fields/Doc";
 import { List } from "../../../new_fields/List";
 import { CollectionViewType } from "../../../client/views/collections/CollectionBaseView";
 import { CollectionTreeView } from "../../../client/views/collections/CollectionTreeView";
 import { CollectionView } from "../../../client/views/collections/CollectionView";
+import { NorthstarSettings, Gateway } from "../../../client/northstar/manager/Gateway";
+import { AttributeTransformationModel } from "../../../client/northstar/core/attribute/AttributeTransformationModel";
+import { ColumnAttributeModel } from "../../../client/northstar/core/attribute/AttributeModel";
+import { HistogramOperation } from "../../../client/northstar/operations/HistogramOperation";
+import { Cast, PromiseValue } from "../../../new_fields/Types";
+import { listSpec } from "../../../new_fields/Schema";
 
 export class CurrentUserUtils {
     private static curr_email: string;
@@ -31,13 +37,13 @@ export class CurrentUserUtils {
         doc.title = this.email;
         doc.data = new List<Doc>();
         doc.excludeFromLibrary = true;
-        doc.optionalRightCollection = Docs.SchemaDocument([], { title: "Pending documents" });
+        doc.optionalRightCollection = Docs.SchemaDocument(["title"], [], { title: "Pending documents" });
         // doc.library = Docs.TreeDocument([doc], { title: `Library: ${CurrentUserUtils.email}` });
         // (doc.library as Doc).excludeFromLibrary = true;
         return doc;
     }
 
-    public static loadCurrentUser(): Promise<any> {
+    public static async loadCurrentUser(): Promise<any> {
         let userPromise = rp.get(DocServer.prepend(RouteStore.getCurrUser)).then(response => {
             if (response) {
                 let obj = JSON.parse(response);
@@ -47,7 +53,7 @@ export class CurrentUserUtils {
                 throw new Error("There should be a user! Why does Dash think there isn't one?");
             }
         });
-        let userDocPromise = rp.get(DocServer.prepend(RouteStore.getUserDocumentId)).then(id => {
+        let userDocPromise = await rp.get(DocServer.prepend(RouteStore.getUserDocumentId)).then(id => {
             if (id) {
                 return DocServer.GetRefField(id).then(field =>
                     runInAction(() => this.user_document = field instanceof Doc ? field : this.createUserDocument(id)));
@@ -55,14 +61,63 @@ export class CurrentUserUtils {
                 throw new Error("There should be a user id! Why does Dash think there isn't one?");
             }
         });
+        try {
+            const getEnvironment = await fetch("/assets/env.json", { redirect: "follow", method: "GET", credentials: "include" });
+            NorthstarSettings.Instance.UpdateEnvironment(await getEnvironment.json());
+            await Gateway.Instance.ClearCatalog();
+            const extraSchemas = Cast(CurrentUserUtils.UserDocument.DBSchemas, listSpec("string"), []);
+            let extras = await Promise.all(extraSchemas.map(async sc => await Gateway.Instance.GetSchema("", sc)));
+            let catprom = CurrentUserUtils.SetNorthstarCatalog(await Gateway.Instance.GetCatalog(), extras);
+            if (catprom) await Promise.all(catprom);
+        } catch (e) {
+
+        }
         return Promise.all([userPromise, userDocPromise]);
     }
 
     /* Northstar catalog ... really just for testing so this should eventually go away */
+    // --------------- Northstar hooks ------------- /
+    static _northstarSchemas: Doc[] = [];
     @observable private static _northstarCatalog?: Catalog;
     @computed public static get NorthstarDBCatalog() { return this._northstarCatalog; }
+
+    @action static SetNorthstarCatalog(ctlog: Catalog, extras: Catalog[]) {
+        CurrentUserUtils.NorthstarDBCatalog = ctlog;
+        if (ctlog && ctlog.schemas) {
+            extras.map(ex => ctlog.schemas!.push(ex));
+            return ctlog.schemas.map(async schema => {
+                let schemaDocuments: Doc[] = [];
+                let attributesToBecomeDocs = CurrentUserUtils.GetAllNorthstarColumnAttributes(schema);
+                await Promise.all(attributesToBecomeDocs.reduce((promises, attr) => {
+                    promises.push(DocServer.GetRefField(attr.displayName! + ".alias").then(action((field: Opt<Field>) => {
+                        if (field instanceof Doc) {
+                            schemaDocuments.push(field);
+                        } else {
+                            var atmod = new ColumnAttributeModel(attr);
+                            let histoOp = new HistogramOperation(schema.displayName!,
+                                new AttributeTransformationModel(atmod, AggregateFunction.None),
+                                new AttributeTransformationModel(atmod, AggregateFunction.Count),
+                                new AttributeTransformationModel(atmod, AggregateFunction.Count));
+                            schemaDocuments.push(Docs.HistogramDocument(histoOp, { width: 200, height: 200, title: attr.displayName! }));
+                        }
+                    })));
+                    return promises;
+                }, [] as Promise<void>[]));
+                return CurrentUserUtils._northstarSchemas.push(Docs.TreeDocument(schemaDocuments, { width: 50, height: 100, title: schema.displayName! }));
+            });
+        }
+    }
     public static set NorthstarDBCatalog(ctlog: Catalog | undefined) { this._northstarCatalog = ctlog; }
 
+    public static AddNorthstarSchema(schema: Schema, schemaDoc: Doc) {
+        if (this._northstarCatalog && CurrentUserUtils._northstarSchemas) {
+            this._northstarCatalog.schemas!.push(schema);
+            CurrentUserUtils._northstarSchemas.push(schemaDoc);
+            let schemas = Cast(CurrentUserUtils.UserDocument.DBSchemas, listSpec("string"), []);
+            schemas.push(schema.displayName!);
+            CurrentUserUtils.UserDocument.DBSchemas = new List<string>(schemas);
+        }
+    }
     public static GetNorthstarSchema(name: string): Schema | undefined {
         return !this._northstarCatalog || !this._northstarCatalog.schemas ? undefined :
             ArrayUtil.FirstOrDefault<Schema>(this._northstarCatalog.schemas, (s: Schema) => s.displayName === name);
-- 
cgit v1.2.3-70-g09d2


From b29a0d1cef60b55f609fcd94ad38232ae557e681 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Thu, 16 May 2019 18:32:57 -0400
Subject: Fixed linter errors

---
 src/client/goldenLayout.d.ts                       |  3 +++
 src/client/northstar/dash-fields/HistogramField.ts |  2 +-
 src/client/northstar/model/ModelHelpers.ts         |  9 +++----
 src/client/util/DragManager.ts                     |  2 +-
 src/client/util/RichTextSchema.tsx                 | 16 +++++------
 src/client/util/TooltipTextMenu.tsx                | 13 ++++-----
 src/client/views/DocumentDecorations.tsx           | 31 +++++++++++-----------
 src/client/views/PresentationView.tsx              |  4 +--
 src/client/views/TemplateMenu.tsx                  |  4 +--
 .../views/collections/CollectionDockingView.tsx    |  5 ++--
 .../views/collections/CollectionSchemaView.tsx     | 10 +++----
 .../views/collections/CollectionTreeView.tsx       |  9 ++++---
 .../collections/collectionFreeForm/MarqueeView.tsx | 13 ++++-----
 .../views/nodes/CollectionFreeFormDocumentView.tsx |  2 +-
 src/client/views/nodes/DocumentView.tsx            |  2 +-
 src/client/views/nodes/FormattedTextBox.tsx        |  8 +++---
 src/client/views/nodes/ImageBox.tsx                |  2 +-
 src/client/views/nodes/KeyValueBox.tsx             |  2 +-
 src/client/views/nodes/KeyValuePair.tsx            |  3 ++-
 src/client/views/nodes/VideoBox.tsx                | 22 +++++++--------
 src/new_fields/CursorField.ts                      |  6 ++---
 src/new_fields/Doc.ts                              |  4 +--
 src/new_fields/ObjectField.ts                      |  2 +-
 .../authentication/models/current_user_utils.ts    |  2 +-
 24 files changed, 91 insertions(+), 85 deletions(-)
 create mode 100644 src/client/goldenLayout.d.ts

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

diff --git a/src/client/goldenLayout.d.ts b/src/client/goldenLayout.d.ts
new file mode 100644
index 000000000..b50240563
--- /dev/null
+++ b/src/client/goldenLayout.d.ts
@@ -0,0 +1,3 @@
+
+declare const GoldenLayout: any;
+export = GoldenLayout;
\ No newline at end of file
diff --git a/src/client/northstar/dash-fields/HistogramField.ts b/src/client/northstar/dash-fields/HistogramField.ts
index aabc77bb2..1ee2189b9 100644
--- a/src/client/northstar/dash-fields/HistogramField.ts
+++ b/src/client/northstar/dash-fields/HistogramField.ts
@@ -52,7 +52,7 @@ export class HistogramField extends ObjectField {
 
     [Copy]() {
         let y = this.HistoOp;
-        let z = this.HistoOp["Copy"];
+        let z = this.HistoOp.Copy;
         return new HistogramField(HistogramOperation.Duplicate(this.HistoOp));
     }
 }
\ No newline at end of file
diff --git a/src/client/northstar/model/ModelHelpers.ts b/src/client/northstar/model/ModelHelpers.ts
index 80bb71224..88e6e72b8 100644
--- a/src/client/northstar/model/ModelHelpers.ts
+++ b/src/client/northstar/model/ModelHelpers.ts
@@ -32,12 +32,9 @@ export class ModelHelpers {
 
     public static GetAggregateParametersIndex(histogramResult: HistogramResult, aggParameters?: AggregateParameters): number {
         return Array.from(histogramResult.aggregateParameters!).findIndex((value, i, set) => {
-            if (set[i] instanceof CountAggregateParameters && value instanceof CountAggregateParameters)
-                return true;
-            if (set[i] instanceof MarginAggregateParameters && value instanceof MarginAggregateParameters)
-                return true;
-            if (set[i] instanceof SumAggregateParameters && value instanceof SumAggregateParameters)
-                return true;
+            if (set[i] instanceof CountAggregateParameters && value instanceof CountAggregateParameters) return true;
+            if (set[i] instanceof MarginAggregateParameters && value instanceof MarginAggregateParameters) return true;
+            if (set[i] instanceof SumAggregateParameters && value instanceof SumAggregateParameters) return true;
             return false;
         });
     }
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 26da34e67..05eb5c38a 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -41,7 +41,7 @@ export function SetupDrag(_reference: React.RefObject<HTMLElement>, docFunc: ()
 export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: number, sourceDoc: Doc) {
     let srcTarg = sourceDoc.proto;
     let draggedDocs: Doc[] = [];
-    let draggedFromDocs: Doc[] = []
+    let draggedFromDocs: Doc[] = [];
     if (srcTarg) {
         let linkToDocs = await DocListCastAsync(srcTarg.linkedToDocs);
         let linkFromDocs = await DocListCastAsync(srcTarg.linkedFromDocs);
diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx
index c0e6f7899..3e3e98206 100644
--- a/src/client/util/RichTextSchema.tsx
+++ b/src/client/util/RichTextSchema.tsx
@@ -97,13 +97,13 @@ export const nodes: { [index: string]: NodeSpec } = {
                     title: dom.getAttribute("title"),
                     alt: dom.getAttribute("alt"),
                     width: Math.min(100, Number(dom.getAttribute("width"))),
-                }
+                };
             }
         }],
         // TODO if we don't define toDom, something weird happens: dragging the image will not move it but clone it. Why?
         toDOM(node) {
-            const attrs = { style: `width: ${node.attrs.width}` }
-            return ["img", { ...node.attrs, ...attrs }]
+            const attrs = { style: `width: ${node.attrs.width}` };
+            return ["img", { ...node.attrs, ...attrs }];
         }
     },
 
@@ -375,7 +375,7 @@ export class ImageResizeView {
                 const currentX = e.pageX;
                 const diffInPx = currentX - startX;
                 self._outer.style.width = `${startWidth + diffInPx}`;
-            }
+            };
 
             const onpointerup = () => {
                 document.removeEventListener("pointermove", onpointermove);
@@ -384,11 +384,11 @@ export class ImageResizeView {
                     view.state.tr.setNodeMarkup(getPos(), null,
                         { src: node.attrs.src, width: self._outer.style.width })
                         .setSelection(view.state.selection));
-            }
+            };
 
-            document.addEventListener("pointermove", onpointermove)
-            document.addEventListener("pointerup", onpointerup)
-        }
+            document.addEventListener("pointermove", onpointermove);
+            document.addEventListener("pointerup", onpointerup);
+        };
 
         this._outer.appendChild(this._handle);
         this._outer.appendChild(this._img);
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index 6eb654319..223921428 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -175,7 +175,7 @@ export class TooltipTextMenu {
             this.linkText.style.width = "150px";
             this.linkText.style.overflow = "hidden";
             this.linkText.style.color = "white";
-            this.linkText.onpointerdown = (e: PointerEvent) => { e.stopPropagation(); }
+            this.linkText.onpointerdown = (e: PointerEvent) => { e.stopPropagation(); };
             let linkBtn = document.createElement("div");
             linkBtn.textContent = ">>";
             linkBtn.style.width = "20px";
@@ -192,8 +192,9 @@ export class TooltipTextMenu {
                         let docid = href.replace(DocServer.prepend("/doc/"), "");
                         DocServer.GetRefField(docid).then(action((f: Opt<Field>) => {
                             if (f instanceof Doc) {
-                                if (DocumentManager.Instance.getDocumentView(f))
+                                if (DocumentManager.Instance.getDocumentView(f)) {
                                     DocumentManager.Instance.getDocumentView(f)!.props.focus(f);
+                                }
                                 else CollectionDockingView.Instance.AddRightSplit(f);
                             }
                         }));
@@ -201,7 +202,7 @@ export class TooltipTextMenu {
                     e.stopPropagation();
                     e.preventDefault();
                 }
-            }
+            };
             this.linkDrag = document.createElement("img");
             this.linkDrag.src = "https://seogurusnyc.com/wp-content/uploads/2016/12/link-1.png";
             this.linkDrag.style.width = "20px";
@@ -216,12 +217,12 @@ export class TooltipTextMenu {
                     {
                         handlers: {
                             dragComplete: action(() => {
-                                let m = dragData.droppedDocuments as Doc[];
+                                let m = dragData.droppedDocuments;
                                 this.makeLink(DocServer.prepend("/doc/" + m[0][Id]));
                             }),
                         },
                         hideSource: false
-                    })
+                    });
             };
             this.linkEditor.appendChild(this.linkDrag);
             this.linkEditor.appendChild(this.linkText);
@@ -239,7 +240,7 @@ export class TooltipTextMenu {
                 e.stopPropagation();
                 e.preventDefault();
             }
-        }
+        };
         this.tooltip.appendChild(this.linkEditor);
     }
 
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index b2c65a31f..7083b1003 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -250,22 +250,21 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 selectedDocs[0].props.removeDocument && selectedDocs[0].props.removeDocument(this._iconDoc);
             }
             if (!this._removeIcon) {
-                if (selectedDocs.length === 1)
+                if (selectedDocs.length === 1) {
                     this.getIconDoc(selectedDocs[0]).then(icon => selectedDocs[0].props.toggleMinimized());
-                else
-                    if (Math.abs(e.pageX - this._downX) < Utils.DRAG_THRESHOLD &&
-                        Math.abs(e.pageY - this._downY) < Utils.DRAG_THRESHOLD) {
-                        let docViews = SelectionManager.ViewsSortedVertically();
-                        let topDocView = docViews[0];
-                        let ind = topDocView.templates.indexOf(Templates.Bullet.Layout);
-                        if (ind !== -1) {
-                            topDocView.templates.splice(ind, 1);
-                            topDocView.props.Document.subBulletDocs = undefined;
-                        } else {
-                            topDocView.addTemplate(Templates.Bullet);
-                            topDocView.props.Document.subBulletDocs = new List<Doc>(docViews.filter(v => v !== topDocView).map(v => v.props.Document.proto!));
-                        }
+                } else if (Math.abs(e.pageX - this._downX) < Utils.DRAG_THRESHOLD &&
+                    Math.abs(e.pageY - this._downY) < Utils.DRAG_THRESHOLD) {
+                    let docViews = SelectionManager.ViewsSortedVertically();
+                    let topDocView = docViews[0];
+                    let ind = topDocView.templates.indexOf(Templates.Bullet.Layout);
+                    if (ind !== -1) {
+                        topDocView.templates.splice(ind, 1);
+                        topDocView.props.Document.subBulletDocs = undefined;
+                    } else {
+                        topDocView.addTemplate(Templates.Bullet);
+                        topDocView.props.Document.subBulletDocs = new List<Doc>(docViews.filter(v => v !== topDocView).map(v => v.props.Document.proto!));
                     }
+                }
             }
             this._removeIcon = false;
         }
@@ -537,9 +536,9 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                         if (temp !== Templates.Bullet.Layout || i === 0) {
                             res.push(temp);
                         }
-                    })
+                    });
                 }
-                return res
+                return res;
             }, [] as string[]);
             let checked = false;
             docTemps.forEach(temp => {
diff --git a/src/client/views/PresentationView.tsx b/src/client/views/PresentationView.tsx
index 098e725c7..7d0dc2913 100644
--- a/src/client/views/PresentationView.tsx
+++ b/src/client/views/PresentationView.tsx
@@ -1,7 +1,7 @@
 import { observer } from "mobx-react";
-import React = require("react")
+import React = require("react");
 import { observable, action, runInAction, reaction } from "mobx";
-import "./PresentationView.scss"
+import "./PresentationView.scss";
 import "./Main.tsx";
 import { DocumentManager } from "../util/DocumentManager";
 import { Utils } from "../../Utils";
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index cfe1b0663..e5b679e24 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -43,7 +43,7 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
     @action
     toggleTemplate = (event: React.ChangeEvent<HTMLInputElement>, template: Template): void => {
         if (event.target.checked) {
-            if (template.Name == "Bullet") {
+            if (template.Name === "Bullet") {
                 let topDocView = this.props.docs[0];
                 topDocView.addTemplate(template);
                 topDocView.props.Document.subBulletDocs = new List<Doc>(this.props.docs.filter(v => v !== topDocView).map(v => v.props.Document.proto!));
@@ -52,7 +52,7 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
             }
             this.props.templates.set(template, true);
         } else {
-            if (template.Name == "Bullet") {
+            if (template.Name === "Bullet") {
                 let topDocView = this.props.docs[0];
                 topDocView.removeTemplate(template);
                 topDocView.props.Document.subBulletDocs = undefined;
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 58f1e33a1..deec64225 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -83,7 +83,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                     child.contentItems[0].remove();
                     this.layoutChanged(document);
                     return true;
-                } else
+                } else {
                     Array.from(child.contentItems).filter((tab: any) => tab.config.component === "DocumentFrameRenderer").some((tab: any, j: number) => {
                         if (Doc.AreProtosEqual(DocumentManager.Instance.getDocumentViewById(tab.config.props.documentId)!.Document, document)) {
                             child.contentItems[j].remove();
@@ -94,8 +94,9 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                         }
                         return false;
                     });
+                }
                 return false;
-            })
+            });
         }
         if (retVal) {
             this.stateChanged();
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index f4ad5b357..497dfde88 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -90,7 +90,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         let fieldContentView = <FieldView {...props} />;
         let reference = React.createRef<HTMLDivElement>();
         let onItemDown = (e: React.PointerEvent) =>
-            (this.props.CollectionView!.props.isSelected() ?
+            (this.props.CollectionView.props.isSelected() ?
                 SetupDrag(reference, () => props.Document, this.props.moveDocument)(e) : undefined);
         let applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => {
             const res = run({ this: doc });
@@ -127,7 +127,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                         }
                         const run = script.run;
                         //TODO This should be able to be refactored to compile the script once
-                        const val = await DocListCastAsync(this.props.Document[this.props.fieldKey])
+                        const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]);
                         val && val.forEach(doc => applyToDoc(doc, run));
                     }}>
                 </EditableView>
@@ -230,14 +230,14 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         DocListCast(this.props.Document.data).map(doc => {
             csv += self.columns.reduce((val, col) => val + (doc[col] ? doc[col]!.toString() : "") + ",", "");
             csv = csv.substr(0, csv.length - 1) + "\n";
-        })
+        });
         csv.substring(0, csv.length - 1);
         let dbName = StrCast(this.props.Document.title);
         let res = await Gateway.Instance.PostSchema(csv, dbName);
         if (self.props.CollectionView.props.addDocument) {
             let schemaDoc = await Docs.DBDocument("https://www.cs.brown.edu/" + dbName, { title: dbName });
             if (schemaDoc) {
-                self.props.CollectionView.props.addDocument(schemaDoc, false); 
+                self.props.CollectionView.props.addDocument(schemaDoc, false);
             }
         }
     }
@@ -263,7 +263,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     get previewDocument(): Doc | undefined {
         const children = DocListCast(this.props.Document[this.props.fieldKey]);
         const selected = children.length > this._selectedIndex ? FieldValue(children[this._selectedIndex]) : undefined;
-        return selected ? (this.previewScript && this.previewScript != "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined;
+        return selected ? (this.previewScript && this.previewScript !== "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined;
     }
     get tableWidth() { return (this.props.PanelWidth() - 2 * this.borderWidth - this.DIVIDER_WIDTH) * (1 - this.splitPercentage / 100); }
     get previewRegionHeight() { return this.props.PanelHeight() - 2 * this.borderWidth; }
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 70c09d97c..6acef434e 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -56,7 +56,7 @@ class TreeView extends React.Component<TreeViewProps> {
         } else {
             CollectionDockingView.Instance.AddRightSplit(this.props.document);
         }
-    };
+    }
 
     get children() {
         return Cast(this.props.document.data, listSpec(Doc), []); // bcz: needed?    .filter(doc => FieldValue(doc));
@@ -184,8 +184,9 @@ class TreeView extends React.Component<TreeViewProps> {
                             {TreeView.GetChildElements(doc instanceof Doc ? [doc] : docList, key !== "data", (doc: Doc) => this.remove(doc, key), this.move, this.props.dropAction)}
                         </div>
                     </ul >);
-                } else
+                } else {
                     bulletType = BulletType.Collapsed;
+                }
             }
         });
         return <div className="treeViewItem-container"
@@ -198,8 +199,8 @@ class TreeView extends React.Component<TreeViewProps> {
         </div>;
     }
     public static GetChildElements(docs: Doc[], allowMinimized: boolean, remove: ((doc: Doc) => void), move: DragManager.MoveFunction, dropAction: dropActionType) {
-        return docs.filter(child => child instanceof Doc && !child.excludeFromLibrary && (allowMinimized || !child.isMinimized)).filter(doc => FieldValue(doc)).map(child =>
-            <TreeView document={child as Doc} key={(child as Doc)[Id]} deleteDoc={remove} moveDocument={move} dropAction={dropAction} />);
+        return docs.filter(child => !child.excludeFromLibrary && (allowMinimized || !child.isMinimized)).map(child =>
+            <TreeView document={child} key={child[Id]} deleteDoc={remove} moveDocument={move} dropAction={dropAction} />);
     }
 }
 
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 12edb2c2a..c3c4115b8 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -63,7 +63,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             e.preventDefault();
             (async () => {
                 let text: string = await navigator.clipboard.readText();
-                let ns = text.split("\n").filter(t => t.trim() != "\r" && t.trim() != "");
+                let ns = text.split("\n").filter(t => t.trim() !== "\r" && t.trim() !== "");
                 for (let i = 0; i < ns.length - 1; i++) {
                     while (!(ns[i].trim() === "" || ns[i].endsWith("-\r") || ns[i].endsWith("-") ||
                         ns[i].endsWith(";\r") || ns[i].endsWith(";") ||
@@ -80,7 +80,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                     let newBox = Docs.TextDocument({ width: 200, height: 35, x: x + indent / 3 * 10, y: y, documentText: "@@@" + line, title: line });
                     this.props.addDocument(newBox, false);
                     y += 40 * this.props.getTransform().Scale;
-                })
+                });
             })();
         } else if (e.key === "b" && e.ctrlKey) {
             //heuristically converts pasted text into a table.
@@ -93,9 +93,10 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             e.preventDefault();
             (async () => {
                 let text: string = await navigator.clipboard.readText();
-                let ns = text.split("\n").filter(t => t.trim() != "\r" && t.trim() != "");
-                while (ns.length > 0 && ns[0].split("\t").length < 2)
+                let ns = text.split("\n").filter(t => t.trim() !== "\r" && t.trim() !== "");
+                while (ns.length > 0 && ns[0].split("\t").length < 2) {
                     ns.splice(0, 1);
+                }
                 if (ns.length > 0) {
                     let columns = ns[0].split("\t");
                     let docList: Doc[] = [];
@@ -109,7 +110,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                         let doc = new Doc();
                         columns.forEach((col, i) => doc[columns[i]] = (values.length > i ? ((values[i].indexOf(Number(values[i]).toString()) !== -1) ? Number(values[i]) : values[i]) : undefined));
                         if (groupAttr) {
-                            doc["_group"] = groupAttr;
+                            doc._group = groupAttr;
                         }
                         doc.title = i.toString();
                         docList.push(doc);
@@ -284,7 +285,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                     //     summarizedDoc.isIconAnimating = new List<number>([scrpt[0], scrpt[1], maxx, maxy, maxw, maxh, Date.now(), 0]);
                     // });
                     this.props.addLiveTextDocument(summary);
-                })
+                });
             }
             else {
                 this.props.addDocument(newCollection, false);
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 7c7ca9e25..d4f660b3f 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -149,7 +149,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
                         let scrpt = this.props.ScreenToLocalTransform().inverse().transformPoint(minx, miny);
                         maximizedDoc.willMaximize = isMinimized;
                         maximizedDoc.isMinimized = false;
-                        maximizedDoc.isIconAnimating = new List<number>([scrpt[0], scrpt[1], Date.now(), isMinimized ? 1 : 0])
+                        maximizedDoc.isIconAnimating = new List<number>([scrpt[0], scrpt[1], Date.now(), isMinimized ? 1 : 0]);
                     }
                 }
             });
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index cf8bcbb42..428dd9b36 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -244,7 +244,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
             const protoDest = destDoc.proto;
             const protoSrc = sourceDoc.proto;
-            if (de.mods == "Control") {
+            if (de.mods === "Control") {
                 let src = protoSrc ? protoSrc : sourceDoc;
                 let dst = protoDest ? protoDest : destDoc;
                 dst.data = src;
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index f24d4ae88..f30022508 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -184,7 +184,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
                 state: field && field.Data ? EditorState.fromJSON(config, JSON.parse(field.Data)) : EditorState.create(config),
                 dispatchTransaction: this.dispatchTransaction,
                 nodeViews: {
-                    image(node, view, getPos) { return new ImageResizeView(node, view, getPos) }
+                    image(node, view, getPos) { return new ImageResizeView(node, view, getPos); }
                 }
             });
             let text = StrCast(this.props.Document.documentText);
@@ -232,9 +232,11 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
                     let docid = href.replace(DocServer.prepend("/doc/"), "").split("?")[0];
                     DocServer.GetRefField(docid).then(action((f: Opt<Field>) => {
                         if (f instanceof Doc) {
-                            if (DocumentManager.Instance.getDocumentView(f))
+                            if (DocumentManager.Instance.getDocumentView(f)) {
                                 DocumentManager.Instance.getDocumentView(f)!.props.focus(f);
-                            else CollectionDockingView.Instance.AddRightSplit(f);
+                            } else {
+                                CollectionDockingView.Instance.AddRightSplit(f);
+                            }
                         }
                     }));
                 }
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 6472ae711..3cc60a6c5 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -165,7 +165,7 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
         else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => (p as ImageField).url.href);
         let nativeWidth = FieldValue(this.Document.nativeWidth, (this.props.PanelWidth as any) as string ? Number((this.props.PanelWidth as any) as string) : 50);
         let interactive = InkingControl.Instance.selectedTool ? "" : "-interactive";
-        let id = this.props.id; // bcz: used to set id = "isExpander" in templates.tsx
+        let id = (this.props as any).id; // bcz: used to set id = "isExpander" in templates.tsx
         return (
             <div id={id} className={`imageBox-cont${interactive}`} onPointerDown={this.onPointerDown} onDrop={this.onDrop} ref={this.createDropTarget} onContextMenu={this.specificContextMenu}>
                 <img id={id} src={paths[Math.min(paths.length, this._photoIndex)]}
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index c9d665ceb..86437a6c1 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -18,7 +18,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
     @observable private _keyInput: string = "";
     @observable private _valueInput: string = "";
     @computed get splitPercentage() { return NumCast(this.props.Document.schemaSplitPercentage, 50); }
-    get fieldDocToLayout() { return this.props.fieldKey ? FieldValue(Cast(this.props.Document[this.props.fieldKey], Doc)) : this.props.Document }
+    get fieldDocToLayout() { return this.props.fieldKey ? FieldValue(Cast(this.props.Document[this.props.fieldKey], Doc)) : this.props.Document; }
 
     constructor(props: FieldViewProps) {
         super(props);
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 5de660d57..4f7919f50 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -46,8 +46,9 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
                 <td className="keyValuePair-td-key" style={{ width: `${this.props.keyWidth}%` }}>
                     <div className="keyValuePair-td-key-container">
                         <button className="keyValuePair-td-key-delete" onClick={() => {
-                            if (Object.keys(props.Document).indexOf(props.fieldKey) !== -1)
+                            if (Object.keys(props.Document).indexOf(props.fieldKey) !== -1) {
                                 props.Document[props.fieldKey] = undefined;
+                            }
                             else props.Document.proto![props.fieldKey] = undefined;
                         }}>
                             X
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 96dc884c8..81c429a02 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -70,7 +70,7 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
     }
 
     @action
-    updateTimecode = () => this.player && (this.props.Document.curPage = this.player.currentTime);
+    updateTimecode = () => this.player && (this.props.Document.curPage = this.player.currentTime)
 
     componentDidMount() {
         if (this.props.setVideoBox) this.props.setVideoBox(this);
@@ -106,31 +106,31 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
                     "user-agent": 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:43.0) Gecko/20100101 Firefox/46.0',
                 },
 
-            }
+            };
             try {
                 let responseSchema: any = {};
-                const videoInfoResponse = await rp.get(DocServer.prepend(RouteStore.corsProxy + "/" + `https://www.youtube.com/watch?v=${videoId}`), videoInfoRequestConfig)
+                const videoInfoResponse = await rp.get(DocServer.prepend(RouteStore.corsProxy + "/" + `https://www.youtube.com/watch?v=${videoId}`), videoInfoRequestConfig);
                 const dataHtml = videoInfoResponse;
                 const start = dataHtml.indexOf('ytplayer.config = ') + 18;
                 const end = dataHtml.indexOf(';ytplayer.load');
-                const subString = dataHtml.substring(start, end)
+                const subString = dataHtml.substring(start, end);
                 const subJson = JSON.parse(subString);
                 const stringSub = subJson.args.player_response;
                 const stringSubJson = JSON.parse(stringSub);
                 const adaptiveFormats = stringSubJson.streamingData.adaptiveFormats;
-                const videoDetails = stringSubJson.videoDetails
-                responseSchema["adaptiveFormats"] = adaptiveFormats;
-                responseSchema["videoDetails"] = videoDetails;
-                resolve(responseSchema)
+                const videoDetails = stringSubJson.videoDetails;
+                responseSchema.adaptiveFormats = adaptiveFormats;
+                responseSchema.videoDetails = videoDetails;
+                resolve(responseSchema);
             }
             catch (err) {
                 console.log(`
                 --- Youtube ---
                 Function: getMp4ForVideo
-                Error: `, err)
-                reject(err)
+                Error: `, err);
+                reject(err);
             }
-        })
+        });
     }
     onPointerDown = (e: React.PointerEvent) => {
         e.preventDefault();
diff --git a/src/new_fields/CursorField.ts b/src/new_fields/CursorField.ts
index 7fd326a5f..fc144222c 100644
--- a/src/new_fields/CursorField.ts
+++ b/src/new_fields/CursorField.ts
@@ -6,17 +6,17 @@ import { serializable, createSimpleSchema, object } from "serializr";
 export type CursorPosition = {
     x: number,
     y: number
-}
+};
 
 export type CursorMetadata = {
     id: string,
     identifier: string
-}
+};
 
 export type CursorData = {
     metadata: CursorMetadata,
     position: CursorPosition
-}
+};
 
 const PositionSchema = createSimpleSchema({
     x: true,
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index de72be3ea..c898f697b 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -42,8 +42,8 @@ export function DocListCastAsync(field: FieldResult, defaultValue?: Doc[]) {
     return list ? Promise.all(list).then(() => list) : Promise.resolve(defaultValue);
 }
 
-export function DocListCast(field: FieldResult) {
-    return Cast(field, listSpec(Doc), []).filter(d => d && d instanceof Doc).map(d => d as Doc);
+export function DocListCast(field: FieldResult): Doc[] {
+    return Cast(field, listSpec(Doc), []).filter(d => d && d instanceof Doc) as Doc[];
 }
 
 @Deserializable("doc").withFields(["id"])
diff --git a/src/new_fields/ObjectField.ts b/src/new_fields/ObjectField.ts
index f276bfa67..51768c6db 100644
--- a/src/new_fields/ObjectField.ts
+++ b/src/new_fields/ObjectField.ts
@@ -6,7 +6,7 @@ export const Parent = Symbol("Parent");
 export const Copy = Symbol("Copy");
 
 export abstract class ObjectField {
-    protected [OnUpdate](diff?: any) { };
+    protected [OnUpdate](diff?: any) { }
     private [Parent]?: RefField | ObjectField;
     abstract [Copy](): ObjectField;
 }
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index 5b63ac356..aef2d3f4a 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -66,7 +66,7 @@ export class CurrentUserUtils {
             NorthstarSettings.Instance.UpdateEnvironment(await getEnvironment.json());
             await Gateway.Instance.ClearCatalog();
             const extraSchemas = Cast(CurrentUserUtils.UserDocument.DBSchemas, listSpec("string"), []);
-            let extras = await Promise.all(extraSchemas.map(async sc => await Gateway.Instance.GetSchema("", sc)));
+            let extras = await Promise.all(extraSchemas.map(sc => Gateway.Instance.GetSchema("", sc)));
             let catprom = CurrentUserUtils.SetNorthstarCatalog(await Gateway.Instance.GetCatalog(), extras);
             if (catprom) await Promise.all(catprom);
         } catch (e) {
-- 
cgit v1.2.3-70-g09d2


From 9d17f2aaaf8ffc229c7b02006070380b0b35e7d3 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Thu, 16 May 2019 21:38:38 -0400
Subject: Small change

---
 src/client/views/collections/CollectionSchemaView.tsx        |  2 +-
 src/client/views/collections/CollectionSubView.tsx           |  2 +-
 src/client/views/collections/CollectionTreeView.tsx          |  4 ++--
 .../collectionFreeForm/CollectionFreeFormView.tsx            | 12 ++++++------
 src/new_fields/Doc.ts                                        |  2 +-
 5 files changed, 11 insertions(+), 11 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 497dfde88..a975d3fef 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -357,7 +357,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     render() {
         library.add(faCog);
         library.add(faPlus);
-        const children = this.children;
+        const children = this.childDocs;
         return (
             <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel}
                 onDrop={(e: React.DragEvent) => this.onDrop(e, {})} onContextMenu={this.onContextMenu} ref={this.createTarget}>
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index ffd3e0659..864fdfa4b 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -47,7 +47,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
             this.createDropTarget(ele);
         }
 
-        get children() {
+        get childDocs() {
             //TODO tfs: This might not be what we want?
             //This linter error can't be fixed because of how js arguments work, so don't switch this to filter(FieldValue)
             return DocListCast(this.props.Document[this.props.fieldKey]);
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 3fcc2bc70..35a9f34cf 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -223,10 +223,10 @@ export class CollectionTreeView extends CollectionSubView(Document) {
     }
     render() {
         let dropAction = StrCast(this.props.Document.dropAction, "alias") as dropActionType;
-        if (!this.children) {
+        if (!this.childDocs) {
             return (null);
         }
-        let childElements = TreeView.GetChildElements(this.children, false, this.remove, this.props.moveDocument, dropAction);
+        let childElements = TreeView.GetChildElements(this.childDocs, false, this.remove, this.props.moveDocument, dropAction);
 
         return (
             <div id="body" className="collectionTreeView-dropTarget"
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 6e4c79e62..ccc81f1ad 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -72,7 +72,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     }
     public getActiveDocuments = () => {
         const curPage = FieldValue(this.Document.curPage, -1);
-        return this.children.filter(doc => {
+        return this.childDocs.filter(doc => {
             var page = NumCast(doc.page, -1);
             return page === curPage || page === -1;
         });
@@ -90,7 +90,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
                 let y = yp - de.data.yOffset / zoom;
                 let dropX = NumCast(de.data.droppedDocuments[0].x);
                 let dropY = NumCast(de.data.droppedDocuments[0].y);
-                de.data.droppedDocuments.map(d => {
+                de.data.droppedDocuments.forEach(d => {
                     d.x = x + NumCast(d.x) - dropX;
                     d.y = y + NumCast(d.y) - dropY;
                     if (!NumCast(d.width)) {
@@ -136,7 +136,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         if (!e.cancelBubble) {
             let x = this.Document.panX || 0;
             let y = this.Document.panY || 0;
-            let docs = this.children || [];
+            let docs = this.childDocs || [];
             let [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY);
             if (!this.isAnnotationOverlay) {
                 let minx = docs.length ? NumCast(docs[0].x) : 0;
@@ -180,7 +180,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         // if (!this.props.active()) {
         //     return;
         // }
-        let childSelected = this.children.some(doc => {
+        let childSelected = this.childDocs.some(doc => {
             var dv = DocumentManager.Instance.getDocumentView(doc);
             return dv && SelectionManager.IsSelected(dv) ? true : false;
         });
@@ -239,7 +239,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     }
 
     bringToFront = (doc: Doc) => {
-        const docs = this.children;
+        const docs = this.childDocs;
         docs.slice().sort((doc1, doc2) => {
             if (doc1 === doc) return 1;
             if (doc2 === doc) return -1;
@@ -306,7 +306,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     @computed.struct
     get views() {
         let curPage = FieldValue(this.Document.curPage, -1);
-        let docviews = this.children.reduce((prev, doc) => {
+        let docviews = this.childDocs.reduce((prev, doc) => {
             if (!(doc instanceof Doc)) return prev;
             var page = NumCast(doc.page, -1);
             if (page === curPage || page === -1) {
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index c898f697b..f76999627 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -43,7 +43,7 @@ export function DocListCastAsync(field: FieldResult, defaultValue?: Doc[]) {
 }
 
 export function DocListCast(field: FieldResult): Doc[] {
-    return Cast(field, listSpec(Doc), []).filter(d => d && d instanceof Doc) as Doc[];
+    return Cast(field, listSpec(Doc), []).filter(d => d instanceof Doc) as Doc[];
 }
 
 @Deserializable("doc").withFields(["id"])
-- 
cgit v1.2.3-70-g09d2


From 2c8aaae6f026199e3675f5e7b4677724d5089ae7 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 17 May 2019 14:53:09 -0400
Subject: added something to follow links in current tab ?

---
 src/client/util/DocumentManager.ts                 | 33 +++++++++++++---------
 .../views/collections/CollectionSchemaView.tsx     |  7 -----
 .../views/nodes/CollectionFreeFormDocumentView.tsx |  2 +-
 3 files changed, 20 insertions(+), 22 deletions(-)

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

diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index c6962ad8d..d06af6dd5 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -1,11 +1,14 @@
 import { computed, observable } from 'mobx';
 import { DocumentView } from '../views/nodes/DocumentView';
-import { Doc, DocListCast } from '../../new_fields/Doc';
+import { Doc, DocListCast, Opt } from '../../new_fields/Doc';
 import { FieldValue, Cast, NumCast, BoolCast } from '../../new_fields/Types';
 import { listSpec } from '../../new_fields/Schema';
 import { undoBatch } from './UndoManager';
 import { CollectionDockingView } from '../views/collections/CollectionDockingView';
 import { Id } from '../../new_fields/RefField';
+import { CollectionView } from '../views/collections/CollectionView';
+import { CollectionPDFView } from '../views/collections/CollectionPDFView';
+import { CollectionVideoView } from '../views/collections/CollectionVideoView';
 
 
 export class DocumentManager {
@@ -27,31 +30,33 @@ export class DocumentManager {
         // this.DocumentViews = new Array<DocumentView>();
     }
 
-    public getDocumentViewById(id: string): DocumentView | null {
+    public getDocumentViewById(id: string, preferredCollection?: CollectionView | CollectionPDFView | CollectionVideoView): DocumentView | null {
 
         let toReturn: DocumentView | null = null;
+        let passes = preferredCollection ? [preferredCollection, undefined] : [undefined];
 
-        //gets document view that is in a freeform canvas collection
-        DocumentManager.Instance.DocumentViews.map(view => {
-            if (view.props.Document[Id] === id) {
-                toReturn = view;
-                return;
-            }
-        });
-        if (!toReturn) {
+        for (let i = 0; i < passes.length; i++) {
             DocumentManager.Instance.DocumentViews.map(view => {
-                let doc = view.props.Document.proto;
-                if (doc && doc[Id] === id) {
+                if (view.props.Document[Id] === id && (!passes[i] || view.props.ContainingCollectionView === preferredCollection)) {
                     toReturn = view;
+                    return;
                 }
             });
+            if (!toReturn) {
+                DocumentManager.Instance.DocumentViews.map(view => {
+                    let doc = view.props.Document.proto;
+                    if (doc && doc[Id] === id && (!passes[i] || view.props.ContainingCollectionView === preferredCollection)) {
+                        toReturn = view;
+                    }
+                });
+            }
         }
 
         return toReturn;
     }
 
-    public getDocumentView(toFind: Doc): DocumentView | null {
-        return this.getDocumentViewById(toFind[Id]);
+    public getDocumentView(toFind: Doc, preferredCollection?: CollectionView | CollectionPDFView | CollectionVideoView): DocumentView | null {
+        return this.getDocumentViewById(toFind[Id], preferredCollection);
     }
 
     public getDocumentViews(toFind: Doc): DocumentView[] {
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 497dfde88..e2b90e26d 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -24,14 +24,7 @@ import { Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types";
 import { listSpec } from "../../../new_fields/Schema";
 import { List } from "../../../new_fields/List";
 import { Id } from "../../../new_fields/RefField";
-import { isUndefined } from "typescript-collections/dist/lib/util";
-import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
 import { Gateway } from "../../northstar/manager/Gateway";
-import { DocServer } from "../../DocServer";
-import { ColumnAttributeModel } from "../../northstar/core/attribute/AttributeModel";
-import { HistogramOperation } from "../../northstar/operations/HistogramOperation";
-import { AggregateFunction } from "../../northstar/model/idea/idea";
-import { AttributeTransformationModel } from "../../northstar/core/attribute/AttributeTransformationModel";
 import { Docs } from "../../documents/Documents";
 import { ContextMenu } from "../ContextMenu";
 
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 001ce3095..00aa71656 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -187,7 +187,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
                 // ...(maximizedDocs ? maximizedDocs : []),
                 // ...(summarizedDocs ? summarizedDocs : []),];
                 if (expandedDocs.length) {   // bcz: need a better way to associate behaviors with click events on widget-documents
-                    let hasView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0]);
+                    let hasView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView);
                     if (!hasView && ((altKey && !this.props.Document.maximizeOnRight) || (!altKey && this.props.Document.maximizeOnRight))) {
                         let dataDocs = DocListCast(CollectionDockingView.Instance.props.Document.data);
                         if (dataDocs) {
-- 
cgit v1.2.3-70-g09d2


From 5220b9dc1f416a5e592fd359fb31033c63602e77 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Fri, 17 May 2019 23:16:11 -0400
Subject: fixed sorting within Schemas

---
 src/client/views/collections/CollectionSchemaView.tsx | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index e2b90e26d..2b4361e50 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -66,8 +66,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
 
     renderCell = (rowProps: CellInfo) => {
         let props: FieldViewProps = {
-            Document: rowProps.value[0],
-            fieldKey: rowProps.value[1],
+            Document: rowProps.original,
+            fieldKey: rowProps.column.id as string,
             ContainingCollectionView: this.props.CollectionView,
             isSelected: returnFalse,
             select: emptyFunction,
@@ -79,6 +79,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             whenActiveChanged: emptyFunction,
             PanelHeight: returnZero,
             PanelWidth: returnZero,
+            addDocTab: this.props.addDocTab,
         };
         let fieldContentView = <FieldView {...props} />;
         let reference = React.createRef<HTMLDivElement>();
@@ -296,6 +297,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                         parentActive={this.props.active}
                         whenActiveChanged={this.props.whenActiveChanged}
                         bringToFront={emptyFunction}
+                        addDocTab={this.props.addDocTab}
                     />
                 </div>)}
             <input className="collectionSchemaView-input" value={this.previewScript} onChange={this.onPreviewScriptChange}
@@ -358,7 +360,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                     <ReactTable data={children} page={0} pageSize={children.length} showPagination={false}
                         columns={this.columns.map(col => ({
                             Header: col,
-                            accessor: (doc: Doc) => [doc, col],
+                            accessor: (doc: Doc) => doc ? doc[col] : 0,
                             id: col
                         }))}
                         column={{ ...ReactTableDefaults.column, Cell: this.renderCell, }}
-- 
cgit v1.2.3-70-g09d2


From 764755f0b025eb3be234d53090ed1fce9a0e1300 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Sat, 18 May 2019 01:09:15 -0400
Subject: Shrunk context menu text Uncapitalized header of columns in schema
 Added dragging to columns of schema

---
 src/client/views/ContextMenu.scss                  | 31 ++++----
 .../views/collections/CollectionSchemaView.scss    | 85 +++++++++++++++-------
 .../views/collections/CollectionSchemaView.tsx     | 23 ++++--
 3 files changed, 94 insertions(+), 45 deletions(-)

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

diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss
index 3b1b18f88..0a14c8ce7 100644
--- a/src/client/views/ContextMenu.scss
+++ b/src/client/views/ContextMenu.scss
@@ -1,24 +1,25 @@
 @import "globalCssVariables";
+
 .contextMenu-cont {
-  position: absolute;
-  display: flex;
-  z-index: $contextMenu-zindex;
-  box-shadow: $intermediate-color 0.2vw 0.2vw 0.4vw;
-  flex-direction: column;
+    position: absolute;
+    display: flex;
+    z-index: $contextMenu-zindex;
+    box-shadow: $intermediate-color 0.2vw 0.2vw 0.4vw;
+    flex-direction: column;
 }
 
 .contextMenu-item:first-child {
-  background: $intermediate-color;
-  color: $light-color;
+    background: $intermediate-color;
+    color: $light-color;
 }
 
 .contextMenu-item:first-child::placeholder {
-  color: $light-color;
+    color: $light-color;
 }
 
 .contextMenu-item:first-child:hover {
-  background: $intermediate-color;
-  color: $light-color;
+    background: $intermediate-color;
+    color: $light-color;
 }
 
 .subMenu-cont {
@@ -49,16 +50,16 @@
     border-bottom-style: solid;
     padding: 10px;
     white-space: nowrap;
-    font-size: 1.5vw;
+    font-size: 1vw;
 }
 
 .contextMenu-item:hover {
-  transition: all 0.1s;
-  background: $lighter-alt-accent;
+    transition: all 0.1s;
+    background: $lighter-alt-accent;
 }
 
 .contextMenu-description {
-    font-size: 1.5vw;
+    font-size: 1vw;
     text-align: left;
     width: 8vw;
     display: inline; //need this?
@@ -66,4 +67,4 @@
 
 .icon-background {
     background-color: #DDDDDD;
-}
+}
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 5e9d2ac67..df5c52d01 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -4,7 +4,7 @@
 
 .collectionSchemaView-container {
     border-width: $COLLECTION_BORDER_WIDTH;
-    border-color : $intermediate-color;
+    border-color: $intermediate-color;
     border-style: solid;
     border-radius: $border-radius;
     box-sizing: border-box;
@@ -14,46 +14,52 @@
 
     .collectionSchemaView-cellContents {
         height: $MAX_ROW_HEIGHT;
+
         img {
-            width:auto;
+            width: auto;
             max-height: $MAX_ROW_HEIGHT;
         }
     }
-    
+
     .collectionSchemaView-previewRegion {
         position: relative;
         background: $light-color;
         float: left;
         height: 100%;
+
         .collectionSchemaView-previewDoc {
             height: 100%;
-            width: 100%; 
+            width: 100%;
             position: absolute;
         }
+
         .collectionSchemaView-input {
             position: absolute;
             max-width: 150px;
             width: 100%;
             bottom: 0px;
         }
+
         .documentView-node:first-child {
             position: relative;
             background: $light-color;
         }
     }
+
     .collectionSchemaView-previewHandle {
         position: absolute;
         height: 15px;
-        width: 15px; 
-        z-index: 20; 
-        right: 0; 
-        top: 20px; 
-        background: Black ;
+        width: 15px;
+        z-index: 20;
+        right: 0;
+        top: 20px;
+        background: Black;
     }
-    .collectionSchemaView-dividerDragger{
-        position: relative; 
-        background: black; 
-        float: left; 
+
+    .collectionSchemaView-dividerDragger {
+        position: relative;
+        background: black;
+        float: left;
         height: 37px;
         width: 20px;
         z-index: 20;
@@ -61,6 +67,7 @@
         top: 0;
         background: $main-accent;
     }
+
     .collectionSchemaView-columnsHandle {
         position: absolute;
         height: 37px;
@@ -70,6 +77,7 @@
         bottom: 0;
         background: $main-accent;
     }
+
     .collectionSchemaView-colDividerDragger {
         position: relative;
         box-sizing: border-box;
@@ -78,6 +86,7 @@
         float: top;
         width: 100%;
     }
+
     .collectionSchemaView-dividerDragger {
         position: relative;
         box-sizing: border-box;
@@ -86,11 +95,13 @@
         float: left;
         height: 100%;
     }
+
     .collectionSchemaView-tableContainer {
         position: relative;
         float: left;
         height: 100%;
     }
+
     .ReactTable {
         // position: absolute; // display: inline-block;
         // overflow: auto;
@@ -99,6 +110,7 @@
         background: $light-color;
         box-sizing: border-box;
         border: none !important;
+
         .rt-table {
             overflow-y: auto;
             overflow-x: auto;
@@ -107,26 +119,32 @@
             direction: ltr; // direction:rtl;
             // display:block;
         }
+
         .rt-tbody {
             //direction: ltr;
             direction: rtl;
         }
+
         .rt-tr-group {
             direction: ltr;
             max-height: $MAX_ROW_HEIGHT;
         }
+
         .rt-td {
             border-width: 1px;
             border-right-color: $intermediate-color;
+
             .imageBox-cont {
                 position: relative;
                 max-height: 100%;
             }
+
             .imageBox-cont img {
                 object-fit: contain;
                 max-width: 100%;
                 height: 100%;
             }
+
             .videoBox-cont {
                 object-fit: contain;
                 width: auto;
@@ -134,15 +152,17 @@
             }
         }
     }
+
     .ReactTable .rt-thead.-header {
         background: $intermediate-color;
         color: $light-color;
-        text-transform: uppercase;
+        // text-transform: uppercase;
         letter-spacing: 2px;
         font-size: 12px;
         height: 30px;
         padding-top: 4px;
     }
+
     .ReactTable .rt-th,
     .ReactTable .rt-td {
         max-height: $MAX_ROW_HEIGHT;
@@ -150,32 +170,36 @@
         font-size: 13px;
         text-align: center;
     }
+
     .ReactTable .rt-tbody .rt-tr-group:last-child {
         border-bottom: $intermediate-color;
         border-bottom-style: solid;
         border-bottom-width: 1;
     }
+
     .documentView-node-topmost {
-        text-align:left;
+        text-align: left;
         transform-origin: center top;
         display: inline-block;
     }
+
     .documentView-node:first-child {
         background: $light-color;
     }
 }
+
 //options menu styling
 #schemaOptionsMenuBtn {
     position: absolute;
     height: 20px;
     width: 20px;
     border-radius: 50%;
-    z-index: 21; 
+    z-index: 21;
     right: 4px;
-    top: 4px; 
+    top: 4px;
     pointer-events: auto;
-    background-color:black;
-    display:inline-block;
+    background-color: black;
+    display: inline-block;
     padding: 0px;
     font-size: 100%;
 }
@@ -189,10 +213,12 @@ ul {
     padding: 0px;
     margin: 0px;
 }
+
 .schema-options-subHeader {
     color: $intermediate-color;
     margin-bottom: 5px;
 }
+
 #schemaOptionsMenuBtn:hover {
     transform: scale(1.15);
 }
@@ -202,15 +228,15 @@ ul {
     font-size: 12px;
 }
 
-  #options-flyout-div {
+#options-flyout-div {
     text-align: left;
-    padding:0px;
+    padding: 0px;
     z-index: 100;
     font-family: $sans-serif;
     padding-left: 5px;
-  }
+}
 
-  #schema-col-checklist {
+#schema-col-checklist {
     overflow: scroll;
     text-align: left;
     //background-color: $light-color-secondary;
@@ -218,8 +244,8 @@ ul {
     max-height: 175px;
     font-family: $sans-serif;
     font-size: 12px;
-  }
-  
+}
+
 
 .Resizer {
     box-sizing: border-box;
@@ -227,6 +253,7 @@ ul {
     opacity: 0.5;
     z-index: 1;
     background-clip: padding-box;
+
     &.horizontal {
         height: 11px;
         margin: -5px 0;
@@ -234,22 +261,26 @@ ul {
         border-bottom: 5px solid rgba(255, 255, 255, 0);
         cursor: row-resize;
         width: 100%;
+
         &:hover {
             border-top: 5px solid rgba(0, 0, 0, 0.5);
             border-bottom: 5px solid rgba(0, 0, 0, 0.5);
         }
     }
+
     &.vertical {
         width: 11px;
         margin: 0 -5px;
         border-left: 5px solid rgba(255, 255, 255, 0);
         border-right: 5px solid rgba(255, 255, 255, 0);
         cursor: col-resize;
+
         &:hover {
             border-left: 5px solid rgba(0, 0, 0, 0.5);
             border-right: 5px solid rgba(0, 0, 0, 0.5);
         }
     }
+
     &:hover {
         -webkit-transition: all 2s ease;
         transition: all 2s ease;
@@ -270,10 +301,12 @@ ul {
         -ms-flex-direction: column;
         flex-direction: column;
     }
+
     header {
         padding: 1rem;
         background: #eee;
     }
+
     footer {
         padding: 1rem;
         background: #eee;
@@ -287,10 +320,12 @@ ul {
         display: flex;
         flex-direction: column;
     }
+
     header {
         padding: 1rem;
         background: #eee;
     }
+
     footer {
         padding: 1rem;
         background: #eee;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index c6b0ff014..f15da41ff 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -64,6 +64,21 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @computed get columns() { return Cast(this.props.Document.schemaColumns, listSpec("string"), []); }
     @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
 
+    @computed get tableColumns() {
+        return this.columns.map(col => {
+            const ref = React.createRef<HTMLParagraphElement>();
+            return {
+                Header: <p ref={ref} onPointerDown={SetupDrag(ref, () => this.onHeaderDrag(col))}>{col}</p>,
+                accessor: (doc: Doc) => doc ? doc[col] : 0,
+                id: col
+            };
+        });
+    }
+
+    onHeaderDrag = (columnName: string) => {
+        return this.props.Document;
+    }
+
     renderCell = (rowProps: CellInfo) => {
         let props: FieldViewProps = {
             Document: rowProps.original,
@@ -349,6 +364,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             <div className="collectionSchemaView-dividerDragger" onPointerDown={this.onDividerDown} style={{ width: `${this.DIVIDER_WIDTH}px` }} />;
     }
 
+
+
     render() {
         library.add(faCog);
         library.add(faPlus);
@@ -358,11 +375,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                 onDrop={(e: React.DragEvent) => this.onDrop(e, {})} onContextMenu={this.onContextMenu} ref={this.createTarget}>
                 <div className="collectionSchemaView-tableContainer" style={{ width: `${this.tableWidth}px` }}>
                     <ReactTable data={children} page={0} pageSize={children.length} showPagination={false}
-                        columns={this.columns.map(col => ({
-                            Header: col,
-                            accessor: (doc: Doc) => doc ? doc[col] : 0,
-                            id: col
-                        }))}
+                        columns={this.tableColumns}
                         column={{ ...ReactTableDefaults.column, Cell: this.renderCell, }}
                         getTrProps={this.getTrProps}
                     />
-- 
cgit v1.2.3-70-g09d2

