From f6e8b7a0f8a13ddf059cf701e46b8cbb8d9228f7 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 14 Jun 2019 17:27:49 -0400
Subject: added page fwd/back/goto

---
 src/client/views/nodes/FieldView.tsx | 2 ++
 1 file changed, 2 insertions(+)

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

diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 5a83de8e3..cf6d2012f 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -18,6 +18,7 @@ import { FormattedTextBox } from "./FormattedTextBox";
 import { IconBox } from "./IconBox";
 import { ImageBox } from "./ImageBox";
 import { VideoBox } from "./VideoBox";
+import { PDFBox } from "./PDFBox";
 
 
 //
@@ -44,6 +45,7 @@ export interface FieldViewProps {
     PanelWidth: () => number;
     PanelHeight: () => number;
     setVideoBox?: (player: VideoBox) => void;
+    setPdfBox?: (player: PDFBox) => void;
 }
 
 @observer
-- 
cgit v1.2.3-70-g09d2


From 8c64ffd92e382050bc8727981cf9fb830e4f02a7 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Mon, 17 Jun 2019 23:04:07 -0400
Subject: Added share with user functionality

---
 src/client/views/nodes/DocumentView.tsx | 48 +++++++++++++++++++++++++--------
 src/client/views/nodes/FieldView.tsx    |  2 +-
 src/server/RouteStore.ts                |  1 +
 src/server/database.ts                  |  4 +--
 src/server/index.ts                     | 11 ++++++++
 5 files changed, 52 insertions(+), 14 deletions(-)

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

diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 9d0206e48..942228e71 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1,11 +1,11 @@
 import { library } from '@fortawesome/fontawesome-svg-core';
 import { faAlignCenter, faCaretSquareRight, faCompressArrowsAlt, faExpandArrowsAlt, faLayerGroup, faSquare, faTrash, faConciergeBell, faFolder, faMapPin, faLink, faFingerprint, faCrosshairs, faDesktop } from '@fortawesome/free-solid-svg-icons';
-import { action, computed, IReactionDisposer, reaction, trace, observable } from "mobx";
+import { action, computed, IReactionDisposer, reaction, trace, observable, runInAction } from "mobx";
 import { observer } from "mobx-react";
 import { Doc, DocListCast, HeightSym, Opt, WidthSym, DocListCastAsync } from "../../../new_fields/Doc";
 import { List } from "../../../new_fields/List";
 import { ObjectField } from "../../../new_fields/ObjectField";
-import { createSchema, makeInterface } from "../../../new_fields/Schema";
+import { createSchema, makeInterface, listSpec } from "../../../new_fields/Schema";
 import { BoolCast, Cast, FieldValue, StrCast, NumCast, PromiseValue } from "../../../new_fields/Types";
 import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
 import { emptyFunction, Utils } from "../../../Utils";
@@ -26,10 +26,12 @@ import { DocComponent } from "../DocComponent";
 import { PresentationView } from "../PresentationView";
 import { Template } from "./../Templates";
 import { DocumentContentsView } from "./DocumentContentsView";
+import * as rp from "request-promise";
 import "./DocumentView.scss";
 import React = require("react");
 import { Id, Copy } from '../../../new_fields/FieldSymbols';
 import { ContextMenuProps } from '../ContextMenuItem';
+import { RouteStore } from '../../../server/RouteStore';
 const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this?
 
 library.add(faTrash);
@@ -452,7 +454,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     }
 
     @action
-    onContextMenu = (e: React.MouseEvent): void => {
+    onContextMenu = async (e: React.MouseEvent): Promise<void> => {
+        e.persist();
         e.stopPropagation();
         if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3 ||
             e.isDefaultPrevented()) {
@@ -483,14 +486,37 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(DocServer.prepend("/doc/" + this.props.Document[Id])), icon: "link" });
         cm.addItem({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]), icon: "fingerprint" });
         cm.addItem({ description: "Delete", event: this.deleteClicked, icon: "trash" });
-        if (!this.topMost) {
-            // DocumentViews should stop propagation of this event
-            e.stopPropagation();
-        }
-        ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
-        if (!SelectionManager.IsSelected(this)) {
-            SelectionManager.SelectDoc(this, false);
-        }
+        type User = { email: string, userDocumentId: string };
+        const users: User[] = JSON.parse(await rp.get(DocServer.prepend(RouteStore.getUsers)));
+        let usersMenu: ContextMenuProps[] = users.filter(({ email }) => email !== CurrentUserUtils.email).map(({ email, userDocumentId }) => ({
+            description: email, event: async () => {
+                const userDocument = await Cast(DocServer.GetRefField(userDocumentId), Doc);
+                if (!userDocument) {
+                    throw new Error(`Couldn't get user document of user ${email}`);
+                }
+                const notifDoc = await Cast(userDocument.optionalRightCollection, Doc);
+                if (notifDoc instanceof Doc) {
+                    const data = await Cast(notifDoc.data, listSpec(Doc));
+                    const sharedDoc = Doc.MakeAlias(this.props.Document);
+                    if (data) {
+                        data.push(sharedDoc);
+                    } else {
+                        notifDoc.data = new List([sharedDoc]);
+                    }
+                }
+            }
+        }));
+        runInAction(() => {
+            cm.addItem({ description: "Share...", subitems: usersMenu });
+            if (!this.topMost) {
+                // DocumentViews should stop propagation of this event
+                e.stopPropagation();
+            }
+            ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15);
+            if (!SelectionManager.IsSelected(this)) {
+                SelectionManager.SelectDoc(this, false);
+            }
+        });
     }
 
     onPointerEnter = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = true; };
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index cf6d2012f..4738e90d7 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -109,7 +109,7 @@ export class FieldView extends React.Component<FieldViewProps> {
         }
         else if (field instanceof List) {
             return (<div>
-                {field.map(f => f instanceof Doc ? f.title : f.toString()).join(", ")}
+                {field.map(f => f instanceof Doc ? f.title : (f && f.toString && f.toString())).join(", ")}
             </div>);
         }
         // bcz: this belongs here, but it doesn't render well so taking it out for now
diff --git a/src/server/RouteStore.ts b/src/server/RouteStore.ts
index c4af5cdaa..5c13495ff 100644
--- a/src/server/RouteStore.ts
+++ b/src/server/RouteStore.ts
@@ -16,6 +16,7 @@ export enum RouteStore {
 
     // USER AND WORKSPACES
     getCurrUser = "/getCurrentUser",
+    getUsers = "/getUsers",
     getUserDocumentId = "/getUserDocumentId",
     updateCursor = "/updateCursor",
 
diff --git a/src/server/database.ts b/src/server/database.ts
index 70b3efced..d240bd909 100644
--- a/src/server/database.ts
+++ b/src/server/database.ts
@@ -120,9 +120,9 @@ export class Database {
         }
     }
 
-    public query(query: any): Promise<mongodb.Cursor> {
+    public query(query: any, collectionName = "newDocuments"): Promise<mongodb.Cursor> {
         if (this.db) {
-            return Promise.resolve<mongodb.Cursor>(this.db.collection('newDocuments').find(query));
+            return Promise.resolve<mongodb.Cursor>(this.db.collection(collectionName).find(query));
         } else {
             return new Promise<mongodb.Cursor>(res => {
                 this.onConnect.push(() => res(this.query(query)));
diff --git a/src/server/index.ts b/src/server/index.ts
index b91c91282..7ef542b01 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -203,6 +203,17 @@ addSecureRoute(
     RouteStore.root
 );
 
+addSecureRoute(
+    Method.GET,
+    async (_, res) => {
+        const cursor = await Database.Instance.query({}, "users");
+        const results = await cursor.toArray();
+        res.send(results.map(user => ({ email: user.email, userDocumentId: user.userDocumentId })));
+    },
+    undefined,
+    RouteStore.getUsers
+);
+
 addSecureRoute(
     Method.GET,
     (user, res, req) => {
-- 
cgit v1.2.3-70-g09d2


From f4fcf306e2579b7479610899a01c06fb157d47de Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 18 Jun 2019 12:03:14 -0400
Subject: fixed goldenlayout nesting

---
 .../views/collections/CollectionDockingView.tsx    |  4 +-
 src/client/views/nodes/FieldView.tsx               | 43 +++++++++++-----------
 src/client/views/nodes/KeyValuePair.tsx            |  2 +-
 3 files changed, 24 insertions(+), 25 deletions(-)

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

diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index b5d57a015..4d48cedd8 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -48,9 +48,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
 
     constructor(props: SubCollectionViewProps) {
         super(props);
-        if (!CollectionDockingView.Instance) {
-            CollectionDockingView.Instance = this;
-        }
+        if (props.addDocTab === emptyFunction) CollectionDockingView.Instance = this;
         //Why is this here?
         (window as any).React = React;
         (window as any).ReactDOM = ReactDOM;
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 4738e90d7..1f1582f22 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -85,27 +85,28 @@ export class FieldView extends React.Component<FieldViewProps> {
             return <p>{field.date.toLocaleString()}</p>;
         }
         else if (field instanceof Doc) {
-            let returnHundred = () => 100;
-            return (
-                <DocumentContentsView Document={field}
-                    addDocument={undefined}
-                    addDocTab={this.props.addDocTab}
-                    removeDocument={undefined}
-                    ScreenToLocalTransform={Transform.Identity}
-                    ContentScaling={returnOne}
-                    PanelWidth={returnHundred}
-                    PanelHeight={returnHundred}
-                    isTopMost={true} //TODO Why is this top most?
-                    selectOnLoad={false}
-                    focus={emptyFunction}
-                    isSelected={this.props.isSelected}
-                    select={returnFalse}
-                    layoutKey={"layout"}
-                    ContainingCollectionView={this.props.ContainingCollectionView}
-                    parentActive={this.props.active}
-                    whenActiveChanged={this.props.whenActiveChanged}
-                    bringToFront={emptyFunction} />
-            );
+            return <p><b>{field.title}</b></p>;
+            // let returnHundred = () => 100;
+            // return (
+            //     <DocumentContentsView Document={field}
+            //         addDocument={undefined}
+            //         addDocTab={this.props.addDocTab}
+            //         removeDocument={undefined}
+            //         ScreenToLocalTransform={Transform.Identity}
+            //         ContentScaling={returnOne}
+            //         PanelWidth={returnHundred}
+            //         PanelHeight={returnHundred}
+            //         isTopMost={true} //TODO Why is this top most?
+            //         selectOnLoad={false}
+            //         focus={emptyFunction}
+            //         isSelected={this.props.isSelected}
+            //         select={returnFalse}
+            //         layoutKey={"layout"}
+            //         ContainingCollectionView={this.props.ContainingCollectionView}
+            //         parentActive={this.props.active}
+            //         whenActiveChanged={this.props.whenActiveChanged}
+            //         bringToFront={emptyFunction} />
+            // );
         }
         else if (field instanceof List) {
             return (<div>
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index e8bc17532..dd1bca7f6 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -40,7 +40,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
             focus: emptyFunction,
             PanelWidth: returnZero,
             PanelHeight: returnZero,
-            addDocTab: emptyFunction
+            addDocTab: returnZero,
         };
         let contents = <FieldView {...props} />;
         let fieldKey = Object.keys(props.Document).indexOf(props.fieldKey) !== -1 ? props.fieldKey : "(" + props.fieldKey + ")";
-- 
cgit v1.2.3-70-g09d2

