From 8bdef5c07d3ba7e6c6a8940bb6786805893812c7 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samwilkins333@gmail.com>
Date: Wed, 27 Feb 2019 10:29:53 -0500
Subject: workspaces menu initialized

---
 .../authentication/controllers/WorkspacesMenu.tsx  | 48 ++++++++++++++++++++++
 1 file changed, 48 insertions(+)
 create mode 100644 src/server/authentication/controllers/WorkspacesMenu.tsx

(limited to 'src/server/authentication/controllers/WorkspacesMenu.tsx')

diff --git a/src/server/authentication/controllers/WorkspacesMenu.tsx b/src/server/authentication/controllers/WorkspacesMenu.tsx
new file mode 100644
index 000000000..77e3a9778
--- /dev/null
+++ b/src/server/authentication/controllers/WorkspacesMenu.tsx
@@ -0,0 +1,48 @@
+import * as React from 'react';
+import * as ReactDOM from 'react-dom';
+import { observable, action, configure, reaction, computed } from 'mobx';
+import { observer } from "mobx-react";
+import * as request from 'request'
+
+@observer
+export class WorkspacesMenu extends React.Component {
+    static Instance: WorkspacesMenu;
+    @observable private workspacesExposed: boolean = false;
+    @observable private workspaceIds: Array<string> = [];
+
+    constructor(props: Readonly<{}>) {
+        super(props);
+        WorkspacesMenu.Instance = this;
+    }
+
+    toggle() {
+        action(() => {
+            if (!this.workspacesExposed) {
+                request.get(window.location.origin + "/getAllWorkspaceIds", (error, response, body) => {
+                    this.workspaceIds = body;
+                    console.log(this.workspaceIds);
+                })
+            }
+            this.workspacesExposed = !this.workspacesExposed;
+        });
+    }
+
+    render() {
+        return (
+            <div
+                style={{
+                    width: "150px",
+                    height: "150px",
+                    position: "absolute",
+                    top: 75,
+                    right: 0,
+                    background: "grey",
+                    zIndex: 15,
+                    visibility: this.workspacesExposed ? "visible" : "hidden"
+                }}
+            >
+                {this.workspaceIds.map(s => <li key={s} >${s}</li>)}
+            </div>
+        );
+    }
+}
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From e5d7c2410fba8b4746217699333c9b7a3661e418 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samwilkins333@gmail.com>
Date: Wed, 27 Feb 2019 11:29:55 -0500
Subject: workspaces toggle now loads ids

---
 src/client/views/Main.tsx                          |  4 +-
 .../authentication/controllers/WorkspacesMenu.css  |  3 ++
 .../authentication/controllers/WorkspacesMenu.tsx  | 55 +++++++++++++++++-----
 src/server/index.ts                                |  2 +-
 4 files changed, 48 insertions(+), 16 deletions(-)
 create mode 100644 src/server/authentication/controllers/WorkspacesMenu.css

(limited to 'src/server/authentication/controllers/WorkspacesMenu.tsx')

diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index e55bc693e..90ce8be1a 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -187,8 +187,8 @@ function init() {
                     }} onClick={() => window.location.pathname = "/logout"}>Logout</button>
                     <button style={{
                         position: 'absolute',
-                        top: '50px',
-                        right: '0px',
+                        top: '24px',
+                        left: '4px',
                         width: '150px'
                     }} onClick={() => WorkspacesMenu.Instance.toggle()}>Workspaces</button>
                     <WorkspacesMenu />
diff --git a/src/server/authentication/controllers/WorkspacesMenu.css b/src/server/authentication/controllers/WorkspacesMenu.css
new file mode 100644
index 000000000..b89039965
--- /dev/null
+++ b/src/server/authentication/controllers/WorkspacesMenu.css
@@ -0,0 +1,3 @@
+.ids:hover {
+    color: darkblue;
+}
\ No newline at end of file
diff --git a/src/server/authentication/controllers/WorkspacesMenu.tsx b/src/server/authentication/controllers/WorkspacesMenu.tsx
index 77e3a9778..23a3d35da 100644
--- a/src/server/authentication/controllers/WorkspacesMenu.tsx
+++ b/src/server/authentication/controllers/WorkspacesMenu.tsx
@@ -3,6 +3,7 @@ import * as ReactDOM from 'react-dom';
 import { observable, action, configure, reaction, computed } from 'mobx';
 import { observer } from "mobx-react";
 import * as request from 'request'
+import './WorkspacesMenu.css'
 
 @observer
 export class WorkspacesMenu extends React.Component {
@@ -15,33 +16,61 @@ export class WorkspacesMenu extends React.Component {
         WorkspacesMenu.Instance = this;
     }
 
+    @action
     toggle() {
-        action(() => {
-            if (!this.workspacesExposed) {
-                request.get(window.location.origin + "/getAllWorkspaceIds", (error, response, body) => {
-                    this.workspaceIds = body;
-                    console.log(this.workspaceIds);
-                })
+        if (this.workspacesExposed) {
+            this.workspacesExposed = !this.workspacesExposed;
+        } else {
+            request.get(window.location.origin + "/getAllWorkspaceIds", this.idCallback)
+        }
+    }
+
+    @action.bound
+    idCallback: request.RequestCallback = (error, response, body) => {
+        this.workspaceIds = [];
+        let ids: Array<string> = JSON.parse(body) as Array<string>;
+        if (ids) {
+            for (let i = 0; i < ids.length; i++) {
+                this.workspaceIds.push(ids[i]);
             }
+            console.log(this.workspaceIds);
             this.workspacesExposed = !this.workspacesExposed;
-        });
+        }
+    }
+
+    setWorkspaceId = (e: React.MouseEvent) => {
+
     }
 
     render() {
         return (
             <div
                 style={{
-                    width: "150px",
-                    height: "150px",
+                    width: "auto",
+                    height: "auto",
+                    borderRadius: 5,
                     position: "absolute",
-                    top: 75,
-                    right: 0,
-                    background: "grey",
+                    top: 50,
+                    left: 8,
+                    background: "white",
+                    border: "black solid 2px",
+                    transition: "all 0.3s ease",
                     zIndex: 15,
+                    padding: 10,
                     visibility: this.workspacesExposed ? "visible" : "hidden"
                 }}
             >
-                {this.workspaceIds.map(s => <li key={s} >${s}</li>)}
+                {this.workspaceIds.map(s =>
+                    <li className={"ids"}
+                        key={s}
+                        style={{
+                            listStyleType: "none",
+                            paddingTop: 3,
+                            paddingBottom: 3
+                        }}
+                        onClick={this.setWorkspaceId}
+                    >{s}</li>
+                )}
             </div>
         );
     }
diff --git a/src/server/index.ts b/src/server/index.ts
index 8f740b1d7..1d16f65ed 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -110,7 +110,7 @@ app.get("/getAllWorkspaceIds", (req, res) => {
     if (!dashUser) {
         return;
     }
-    res.send(dashUser.allWorkspaceIds);
+    res.send(JSON.stringify(dashUser.allWorkspaceIds as Array<String>));
 })
 
 app.post("/setActiveWorkspaceId", (req, res) => {
-- 
cgit v1.2.3-70-g09d2


From 23a8f1367a4421ea8a8cbeb6c341705488ebc864 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samwilkins333@gmail.com>
Date: Wed, 27 Feb 2019 11:44:58 -0500
Subject: extracted id from on click

---
 src/server/authentication/controllers/WorkspacesMenu.tsx | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

(limited to 'src/server/authentication/controllers/WorkspacesMenu.tsx')

diff --git a/src/server/authentication/controllers/WorkspacesMenu.tsx b/src/server/authentication/controllers/WorkspacesMenu.tsx
index 23a3d35da..a440ab779 100644
--- a/src/server/authentication/controllers/WorkspacesMenu.tsx
+++ b/src/server/authentication/controllers/WorkspacesMenu.tsx
@@ -39,7 +39,7 @@ export class WorkspacesMenu extends React.Component {
     }
 
     setWorkspaceId = (e: React.MouseEvent) => {
-
+        console.log(e.currentTarget.innerHTML);
     }
 
     render() {
@@ -51,13 +51,12 @@ export class WorkspacesMenu extends React.Component {
                     borderRadius: 5,
                     position: "absolute",
                     top: 50,
-                    left: 8,
+                    left: this.workspacesExposed ? 8 : -500,
                     background: "white",
                     border: "black solid 2px",
-                    transition: "all 0.3s ease",
+                    transition: "all 1s ease",
                     zIndex: 15,
                     padding: 10,
-                    visibility: this.workspacesExposed ? "visible" : "hidden"
                 }}
             >
                 {this.workspaceIds.map(s =>
-- 
cgit v1.2.3-70-g09d2


From dd6c727f9d7836d2d86a9a1e7026eb694eaba500 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samwilkins333@gmail.com>
Date: Wed, 27 Feb 2019 12:53:49 -0500
Subject: slight loading refactor

---
 src/client/views/Main.tsx                                | 12 +++++++++---
 src/server/authentication/controllers/WorkspacesMenu.tsx |  1 +
 2 files changed, 10 insertions(+), 3 deletions(-)

(limited to 'src/server/authentication/controllers/WorkspacesMenu.tsx')

diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 90ce8be1a..d4bfbb52a 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -40,10 +40,11 @@ document.addEventListener("pointerdown", action(function (e: PointerEvent) {
 let mainDocId: string;
 request.get(window.location.origin + "/getActiveWorkspaceId", (error, response, body) => {
     const here = window.location.origin;
+    let workspaceId: string;
     if (body) {
-        mainDocId = body;
+        workspaceId = body;
     } else {
-        mainDocId = Utils.GenerateGuid();
+        workspaceId = Utils.GenerateGuid();
         request.post(here + "/addWorkspaceId", {
             body: {
                 target: mainDocId
@@ -57,9 +58,14 @@ request.get(window.location.origin + "/getActiveWorkspaceId", (error, response,
             json: true
         })
     }
-    init();
+    load(workspaceId);
 })
 
+function load(workspaceId: string) {
+    mainDocId = workspaceId;
+    init();
+}
+
 //runInAction(() => 
 // let doc1 = Documents.TextDocument({ title: "hello" });
 // let doc2 = doc1.MakeDelegate();
diff --git a/src/server/authentication/controllers/WorkspacesMenu.tsx b/src/server/authentication/controllers/WorkspacesMenu.tsx
index a440ab779..b1125384e 100644
--- a/src/server/authentication/controllers/WorkspacesMenu.tsx
+++ b/src/server/authentication/controllers/WorkspacesMenu.tsx
@@ -39,6 +39,7 @@ export class WorkspacesMenu extends React.Component {
     }
 
     setWorkspaceId = (e: React.MouseEvent) => {
+        //Main.load(e.currentTarget.innherHTML)
         console.log(e.currentTarget.innerHTML);
     }
 
-- 
cgit v1.2.3-70-g09d2


From ac0dfd18950cb2b1e70e0df1c5fc7778e393007f Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samwilkins333@gmail.com>
Date: Wed, 27 Feb 2019 13:06:51 -0500
Subject: now loads workspaces from ids

---
 src/client/views/Main.tsx                                |  2 +-
 src/server/authentication/controllers/WorkspacesMenu.tsx | 11 +++++++----
 2 files changed, 8 insertions(+), 5 deletions(-)

(limited to 'src/server/authentication/controllers/WorkspacesMenu.tsx')

diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index d4bfbb52a..2c2149a1e 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -197,7 +197,7 @@ function init() {
                         left: '4px',
                         width: '150px'
                     }} onClick={() => WorkspacesMenu.Instance.toggle()}>Workspaces</button>
-                    <WorkspacesMenu />
+                    <WorkspacesMenu load={load} />
                 </div>),
                 document.getElementById('root'));
         })
diff --git a/src/server/authentication/controllers/WorkspacesMenu.tsx b/src/server/authentication/controllers/WorkspacesMenu.tsx
index b1125384e..8edd63fba 100644
--- a/src/server/authentication/controllers/WorkspacesMenu.tsx
+++ b/src/server/authentication/controllers/WorkspacesMenu.tsx
@@ -5,13 +5,17 @@ import { observer } from "mobx-react";
 import * as request from 'request'
 import './WorkspacesMenu.css'
 
+export interface WorkspaceMenuProps {
+    load: (workspaceId: string) => void;
+}
+
 @observer
-export class WorkspacesMenu extends React.Component {
+export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> {
     static Instance: WorkspacesMenu;
     @observable private workspacesExposed: boolean = false;
     @observable private workspaceIds: Array<string> = [];
 
-    constructor(props: Readonly<{}>) {
+    constructor(props: WorkspaceMenuProps) {
         super(props);
         WorkspacesMenu.Instance = this;
     }
@@ -39,8 +43,7 @@ export class WorkspacesMenu extends React.Component {
     }
 
     setWorkspaceId = (e: React.MouseEvent) => {
-        //Main.load(e.currentTarget.innherHTML)
-        console.log(e.currentTarget.innerHTML);
+        this.props.load(e.currentTarget.innerHTML);
     }
 
     render() {
-- 
cgit v1.2.3-70-g09d2


From f60be11aef0e76cbc636933611962b3e1a4ec71e Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samwilkins333@gmail.com>
Date: Wed, 27 Feb 2019 15:24:51 -0500
Subject: mostly finished workspace manipulation: golden-layout bug when
 creating a new workspace

---
 src/client/views/Main.tsx                          | 48 ++++++++++------------
 .../authentication/controllers/WorkspacesMenu.tsx  | 42 +++++++++++++++----
 .../authentication/controllers/user_controller.ts  |  3 --
 src/server/index.ts                                |  1 -
 4 files changed, 55 insertions(+), 39 deletions(-)

(limited to 'src/server/authentication/controllers/WorkspacesMenu.tsx')

diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 2c2149a1e..febf7489b 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -37,33 +37,27 @@ document.addEventListener("pointerdown", action(function (e: PointerEvent) {
     }
 }), true)
 
-let mainDocId: string;
+// Load the user's active workspace, or create a new one if initial session after signup
 request.get(window.location.origin + "/getActiveWorkspaceId", (error, response, body) => {
-    const here = window.location.origin;
-    let workspaceId: string;
-    if (body) {
-        workspaceId = body;
-    } else {
-        workspaceId = Utils.GenerateGuid();
-        request.post(here + "/addWorkspaceId", {
-            body: {
-                target: mainDocId
-            },
-            json: true
-        })
-        request.post(here + "/setActiveWorkspaceId", {
-            body: {
-                target: mainDocId
-            },
-            json: true
-        })
-    }
-    load(workspaceId);
-})
+    init(body ? body : getNewWorkspace());
+});
 
-function load(workspaceId: string) {
-    mainDocId = workspaceId;
-    init();
+function getNewWorkspace(): string {
+    let newId = Utils.GenerateGuid();
+    const here = window.location.origin;
+    request.post(here + "/addWorkspaceId", {
+        body: {
+            target: newId
+        },
+        json: true
+    })
+    request.post(here + "/setActiveWorkspaceId", {
+        body: {
+            target: newId
+        },
+        json: true
+    })
+    return newId;
 }
 
 //runInAction(() => 
@@ -82,7 +76,7 @@ function load(workspaceId: string) {
 // schemaDocs[4].SetData(KS.Author, "Bob", TextField);
 // schemaDocs.push(doc2);
 // const doc7 = Documents.SchemaDocument(schemaDocs)
-function init() {
+function init(mainDocId: string) {
     Documents.initProtos(() => {
         Utils.EmitCallback(Server.Socket, MessageStore.GetField, mainDocId, (res: any) => {
             console.log("HELLO WORLD")
@@ -197,7 +191,7 @@ function init() {
                         left: '4px',
                         width: '150px'
                     }} onClick={() => WorkspacesMenu.Instance.toggle()}>Workspaces</button>
-                    <WorkspacesMenu load={load} />
+                    <WorkspacesMenu load={init} new={getNewWorkspace} />
                 </div>),
                 document.getElementById('root'));
         })
diff --git a/src/server/authentication/controllers/WorkspacesMenu.tsx b/src/server/authentication/controllers/WorkspacesMenu.tsx
index 8edd63fba..d9d884c14 100644
--- a/src/server/authentication/controllers/WorkspacesMenu.tsx
+++ b/src/server/authentication/controllers/WorkspacesMenu.tsx
@@ -1,12 +1,13 @@
 import * as React from 'react';
 import * as ReactDOM from 'react-dom';
-import { observable, action, configure, reaction, computed } from 'mobx';
+import { observable, action, configure, reaction, computed, ObservableMap } from 'mobx';
 import { observer } from "mobx-react";
 import * as request from 'request'
 import './WorkspacesMenu.css'
 
 export interface WorkspaceMenuProps {
     load: (workspaceId: string) => void;
+    new: () => string;
 }
 
 @observer
@@ -14,10 +15,28 @@ export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> {
     static Instance: WorkspacesMenu;
     @observable private workspacesExposed: boolean = false;
     @observable private workspaceIds: Array<string> = [];
+    @observable private selectedWorkspaceId: string = "";
 
     constructor(props: WorkspaceMenuProps) {
         super(props);
         WorkspacesMenu.Instance = this;
+        this.loadExistingWorkspace = this.loadExistingWorkspace.bind(this);
+        this.addNewWorkspace = this.addNewWorkspace.bind(this);
+    }
+
+    @action
+    addNewWorkspace() {
+        let newId = this.props.new();
+        this.selectedWorkspaceId = newId;
+        this.props.load(newId);
+        this.toggle();
+    }
+
+    @action
+    loadExistingWorkspace = (e: React.MouseEvent<HTMLLIElement, MouseEvent>) => {
+        let id = e.currentTarget.innerHTML;
+        this.props.load(id);
+        this.selectedWorkspaceId = id;
     }
 
     @action
@@ -42,11 +61,8 @@ export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> {
         }
     }
 
-    setWorkspaceId = (e: React.MouseEvent) => {
-        this.props.load(e.currentTarget.innerHTML);
-    }
-
     render() {
+        let p = this.props;
         return (
             <div
                 style={{
@@ -63,15 +79,25 @@ export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> {
                     padding: 10,
                 }}
             >
+                <img
+                    src="https://bit.ly/2IBBkxk"
+                    style={{
+                        width: 20,
+                        height: 20,
+                        marginBottom: 10,
+                        cursor: "grab"
+                    }}
+                    onClick={this.addNewWorkspace}
+                />
                 {this.workspaceIds.map(s =>
                     <li className={"ids"}
                         key={s}
                         style={{
                             listStyleType: "none",
-                            paddingTop: 3,
-                            paddingBottom: 3
+                            color: s === this.selectedWorkspaceId ? "darkblue" : "black",
+                            cursor: "grab"
                         }}
-                        onClick={this.setWorkspaceId}
+                        onClick={this.loadExistingWorkspace}
                     >{s}</li>
                 )}
             </div>
diff --git a/src/server/authentication/controllers/user_controller.ts b/src/server/authentication/controllers/user_controller.ts
index 899912ab7..1f1f43684 100644
--- a/src/server/authentication/controllers/user_controller.ts
+++ b/src/server/authentication/controllers/user_controller.ts
@@ -149,9 +149,6 @@ export let getLogout = (req: Request, res: Response) => {
     const dashUser: DashUserModel | undefined = req.user;
     if (dashUser) {
         dashUser.update({ $set: { didSelectSessionWorkspace: false } }, () => { })
-        console.log("UPDATED :)");
-    } else {
-        console.log("NO USER BY LOGOUT");
     }
     req.logout();
     const sess = req.session;
diff --git a/src/server/index.ts b/src/server/index.ts
index 1d16f65ed..c707f12a0 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -118,7 +118,6 @@ app.post("/setActiveWorkspaceId", (req, res) => {
     if (!dashUser) {
         return;
     }
-    console.log(`Updating active workspace ID to ${req.body.target}`);
     dashUser.update({ $set: { activeWorkspaceId: req.body.target } }, () => { });
 })
 
-- 
cgit v1.2.3-70-g09d2


From 366d085347cdb07ad0d4f982598f6d0d69dca606 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samwilkins333@gmail.com>
Date: Wed, 27 Feb 2019 15:28:18 -0500
Subject: more responsive color displays

---
 src/client/views/Main.tsx                                | 2 +-
 src/server/authentication/controllers/WorkspacesMenu.tsx | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

(limited to 'src/server/authentication/controllers/WorkspacesMenu.tsx')

diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index febf7489b..b59a2a4f7 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -191,7 +191,7 @@ function init(mainDocId: string) {
                         left: '4px',
                         width: '150px'
                     }} onClick={() => WorkspacesMenu.Instance.toggle()}>Workspaces</button>
-                    <WorkspacesMenu load={init} new={getNewWorkspace} />
+                    <WorkspacesMenu load={init} new={getNewWorkspace} active={mainDocId}/>
                 </div>),
                 document.getElementById('root'));
         })
diff --git a/src/server/authentication/controllers/WorkspacesMenu.tsx b/src/server/authentication/controllers/WorkspacesMenu.tsx
index d9d884c14..d48a855fd 100644
--- a/src/server/authentication/controllers/WorkspacesMenu.tsx
+++ b/src/server/authentication/controllers/WorkspacesMenu.tsx
@@ -6,6 +6,7 @@ import * as request from 'request'
 import './WorkspacesMenu.css'
 
 export interface WorkspaceMenuProps {
+    active: string;
     load: (workspaceId: string) => void;
     new: () => string;
 }
@@ -22,6 +23,7 @@ export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> {
         WorkspacesMenu.Instance = this;
         this.loadExistingWorkspace = this.loadExistingWorkspace.bind(this);
         this.addNewWorkspace = this.addNewWorkspace.bind(this);
+        this.selectedWorkspaceId = this.props.active;
     }
 
     @action
-- 
cgit v1.2.3-70-g09d2


From 58858f2f4158e3de3e4d1dddbc85bad8e7edb7f9 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samwilkins333@gmail.com>
Date: Wed, 27 Feb 2019 15:33:32 -0500
Subject: just the bug

---
 src/server/authentication/controllers/WorkspacesMenu.tsx | 1 -
 1 file changed, 1 deletion(-)

(limited to 'src/server/authentication/controllers/WorkspacesMenu.tsx')

diff --git a/src/server/authentication/controllers/WorkspacesMenu.tsx b/src/server/authentication/controllers/WorkspacesMenu.tsx
index d48a855fd..284a8ec66 100644
--- a/src/server/authentication/controllers/WorkspacesMenu.tsx
+++ b/src/server/authentication/controllers/WorkspacesMenu.tsx
@@ -58,7 +58,6 @@ export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> {
             for (let i = 0; i < ids.length; i++) {
                 this.workspaceIds.push(ids[i]);
             }
-            console.log(this.workspaceIds);
             this.workspacesExposed = !this.workspacesExposed;
         }
     }
-- 
cgit v1.2.3-70-g09d2


From 45d9a5bc32aa5d5aa7695c4e6576f3c42f24c5c9 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samwilkins333@gmail.com>
Date: Wed, 27 Feb 2019 17:30:10 -0500
Subject: clean up

---
 src/server/authentication/controllers/WorkspacesMenu.tsx |  5 ++++-
 src/server/authentication/controllers/user_controller.ts | 10 ----------
 src/server/index.ts                                      |  2 +-
 views/workspace.pug                                      | 13 -------------
 4 files changed, 5 insertions(+), 25 deletions(-)
 delete mode 100644 views/workspace.pug

(limited to 'src/server/authentication/controllers/WorkspacesMenu.tsx')

diff --git a/src/server/authentication/controllers/WorkspacesMenu.tsx b/src/server/authentication/controllers/WorkspacesMenu.tsx
index 284a8ec66..94d168a05 100644
--- a/src/server/authentication/controllers/WorkspacesMenu.tsx
+++ b/src/server/authentication/controllers/WorkspacesMenu.tsx
@@ -1,6 +1,6 @@
 import * as React from 'react';
 import * as ReactDOM from 'react-dom';
-import { observable, action, configure, reaction, computed, ObservableMap } from 'mobx';
+import { observable, action, configure, reaction, computed, ObservableMap, runInAction } from 'mobx';
 import { observer } from "mobx-react";
 import * as request from 'request'
 import './WorkspacesMenu.css'
@@ -32,6 +32,9 @@ export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> {
         this.selectedWorkspaceId = newId;
         this.props.load(newId);
         this.toggle();
+        //     setTimeout(action(() => {
+
+        //     }), 100);
     }
 
     @action
diff --git a/src/server/authentication/controllers/user_controller.ts b/src/server/authentication/controllers/user_controller.ts
index 1f1f43684..7b89b5152 100644
--- a/src/server/authentication/controllers/user_controller.ts
+++ b/src/server/authentication/controllers/user_controller.ts
@@ -130,16 +130,6 @@ export let postLogin = (req: Request, res: Response, next: NextFunction) => {
     })(req, res, next);
 };
 
-export let getWorkspaces = (req: Request, res: Response) => {
-    const user: DashUserModel = req.user;
-    if (!user) {
-        return res.redirect("/login");
-    }
-    res.render("workspace.pug", {
-        ids: user.allWorkspaceIds
-    });
-}
-
 /**
  * GET /logout
  * Invokes the logout function on the request
diff --git a/src/server/index.ts b/src/server/index.ts
index c707f12a0..5115142b8 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -17,7 +17,7 @@ import * as bcrypt from "bcrypt-nodejs";
 import { Document } from '../fields/Document';
 import * as io from 'socket.io'
 import * as passportConfig from './authentication/config/passport';
-import { getLogin, postLogin, getSignup, postSignup, getLogout, getEntry, postReset, getForgot, postForgot, getReset, getWorkspaces } from './authentication/controllers/user_controller';
+import { getLogin, postLogin, getSignup, postSignup, getLogout, getEntry, postReset, getForgot, postForgot, getReset } from './authentication/controllers/user_controller';
 const config = require('../../webpack.config');
 const compiler = webpack(config);
 const port = 1050; // default port to listen
diff --git a/views/workspace.pug b/views/workspace.pug
deleted file mode 100644
index 8bbc3e02c..000000000
--- a/views/workspace.pug
+++ /dev/null
@@ -1,13 +0,0 @@
-
-extends ./layout
-
-block content
-    style
-        include ./stylesheets/authentication.css
-    form.form-horizontal(id='workspace-form', method='POST', action='/home')
-        input(type='hidden', name='_csrf', value=_csrf)
-        .overlay(id='overlay_workspaces')
-            h3.workspace-header Select A Workspace
-            ul.workspaceList
-                each val, index in ids
-                    li.workspaceId(onclick='console.log("' + val + '")')= (index + 1) + ') ' + val
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From a3688ff7a274e23e7732700118741021a7468a61 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Mon, 4 Mar 2019 17:24:46 -0500
Subject: fixed rendering workspace menu bug

---
 src/client/views/Main.tsx                                | 11 +++++++----
 src/server/authentication/controllers/WorkspacesMenu.tsx |  1 +
 2 files changed, 8 insertions(+), 4 deletions(-)

(limited to 'src/server/authentication/controllers/WorkspacesMenu.tsx')

diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 8d6c91c26..5a0fb23bd 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -70,7 +70,6 @@ export class Main extends React.Component {
 
     @action
     requestWorkspace = (activeWorkspaceId: string) => {
-        console.log("START LOAD!!!");
         Documents.initProtos(activeWorkspaceId, this.prepareWorkspace);
     }
 
@@ -92,11 +91,15 @@ export class Main extends React.Component {
                 this.mainContainer.Set(KeyStore.ActiveFrame, this.mainfreeform);
             }, 0);
         }
-        console.log("END LOAD!!!");
+    }
+
+    toggleWorkspaces = () => {
+        if (WorkspacesMenu.Instance) {
+            WorkspacesMenu.Instance.toggle()
+        }
     }
 
     render() {
-        console.log("We're rendering!!!");
         let imgRef = React.createRef<HTMLDivElement>();
         let webRef = React.createRef<HTMLDivElement>();
         let textRef = React.createRef<HTMLDivElement>();
@@ -141,7 +144,7 @@ export class Main extends React.Component {
                 <div className="main-buttonDiv" style={{ bottom: '125px' }} >
                     <button onClick={clearDatabase}>Clear Database</button></div>
                 <div className="main-buttonDiv" style={{ top: '25px' }} ref={workspacesRef}>
-                    <button>View Workspaces</button></div>
+                    <button onClick={this.toggleWorkspaces}>View Workspaces</button></div>
                 <button className="main-undoButtons" style={{ bottom: '25px' }} onClick={() => UndoManager.Undo()}>Undo</button>
                 <button className="main-undoButtons" style={{ bottom: '0px' }} onClick={() => UndoManager.Redo()}>Redo</button>
             </div>
diff --git a/src/server/authentication/controllers/WorkspacesMenu.tsx b/src/server/authentication/controllers/WorkspacesMenu.tsx
index 94d168a05..fe93aac2c 100644
--- a/src/server/authentication/controllers/WorkspacesMenu.tsx
+++ b/src/server/authentication/controllers/WorkspacesMenu.tsx
@@ -21,6 +21,7 @@ export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> {
     constructor(props: WorkspaceMenuProps) {
         super(props);
         WorkspacesMenu.Instance = this;
+        console.log("ASSIGNED!");
         this.loadExistingWorkspace = this.loadExistingWorkspace.bind(this);
         this.addNewWorkspace = this.addNewWorkspace.bind(this);
         this.selectedWorkspaceId = this.props.active;
-- 
cgit v1.2.3-70-g09d2


From 6ca68333303d97ce35d4118bacdd21f410bdd017 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Mon, 4 Mar 2019 18:58:27 -0500
Subject: working toward persistence

---
 src/client/views/Main.tsx                                | 15 ++++++++-------
 src/client/views/collections/CollectionFreeFormView.tsx  |  2 +-
 src/server/authentication/controllers/WorkspacesMenu.tsx |  4 ----
 3 files changed, 9 insertions(+), 12 deletions(-)

(limited to 'src/server/authentication/controllers/WorkspacesMenu.tsx')

diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 5a0fb23bd..2f4264ad9 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -49,19 +49,14 @@ export class Main extends React.Component {
 
     initAuthenticationRouters = () => {
         // Load the user's active workspace, or create a new one if initial session after signup
-        request.get(window.location.origin + "/getActiveWorkspaceId", (error, response, body) => {
+        request.get(this.contextualize("getActiveWorkspaceId"), (error, response, body) => {
             this.requestWorkspace(body ? body : this.getNewWorkspace());
         });
     }
 
     getNewWorkspace = (): string => {
         let newId = Utils.GenerateGuid();
-        const here = window.location.origin;
-        request.post(here + "/addWorkspaceId", {
-            body: { target: newId },
-            json: true
-        })
-        request.post(here + "/setActiveWorkspaceId", {
+        request.post(this.contextualize("addWorkspaceId"), {
             body: { target: newId },
             json: true
         })
@@ -70,6 +65,10 @@ export class Main extends React.Component {
 
     @action
     requestWorkspace = (activeWorkspaceId: string) => {
+        request.post(this.contextualize("setActiveWorkspaceId"), {
+            body: { target: activeWorkspaceId },
+            json: true
+        })
         Documents.initProtos(activeWorkspaceId, this.prepareWorkspace);
     }
 
@@ -99,6 +98,8 @@ export class Main extends React.Component {
         }
     }
 
+    contextualize = (extension: string) => window.location.origin + "/" + extension;
+
     render() {
         let imgRef = React.createRef<HTMLDivElement>();
         let webRef = React.createRef<HTMLDivElement>();
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 5e9dcd5d5..43f5fe6d6 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -277,7 +277,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
         const pany: number = -this.props.Document.GetNumber(KeyStore.PanY, 0);
         // const panx: number = this.props.Document.GetNumber(KeyStore.PanX, 0) + this.centeringShiftX;
         // const pany: number = this.props.Document.GetNumber(KeyStore.PanY, 0) + this.centeringShiftY;
-        console.log("center:", this.getLocalTransform().transformPoint(this.centeringShiftX, this.centeringShiftY));
+        // console.log("center:", this.getLocalTransform().transformPoint(this.centeringShiftX, this.centeringShiftY));
 
         return (
             <div className="collectionfreeformview-container"
diff --git a/src/server/authentication/controllers/WorkspacesMenu.tsx b/src/server/authentication/controllers/WorkspacesMenu.tsx
index fe93aac2c..b565af193 100644
--- a/src/server/authentication/controllers/WorkspacesMenu.tsx
+++ b/src/server/authentication/controllers/WorkspacesMenu.tsx
@@ -21,7 +21,6 @@ export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> {
     constructor(props: WorkspaceMenuProps) {
         super(props);
         WorkspacesMenu.Instance = this;
-        console.log("ASSIGNED!");
         this.loadExistingWorkspace = this.loadExistingWorkspace.bind(this);
         this.addNewWorkspace = this.addNewWorkspace.bind(this);
         this.selectedWorkspaceId = this.props.active;
@@ -33,9 +32,6 @@ export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> {
         this.selectedWorkspaceId = newId;
         this.props.load(newId);
         this.toggle();
-        //     setTimeout(action(() => {
-
-        //     }), 100);
     }
 
     @action
-- 
cgit v1.2.3-70-g09d2


From f4a01b9b394a5bdc48e57923567249bb05cb71ff Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Fri, 8 Mar 2019 00:11:04 -0500
Subject: Close to refactor

---
 .vscode/launch.json                                |  2 +-
 src/client/SocketStub.ts                           |  1 +
 src/client/documents/Documents.ts                  |  6 +-
 src/client/views/Main.tsx                          | 79 ++++++++++---------
 .../authentication/controllers/WorkspacesMenu.tsx  | 56 ++++----------
 src/server/database.ts                             | 10 +++
 src/server/index.ts                                | 88 +++++++++++-----------
 7 files changed, 117 insertions(+), 125 deletions(-)

(limited to 'src/server/authentication/controllers/WorkspacesMenu.tsx')

diff --git a/.vscode/launch.json b/.vscode/launch.json
index 5f320d3fe..fb91a1080 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -10,7 +10,7 @@
             "name": "Launch Chrome against localhost",
             "sourceMaps": true,
             "breakOnLoad": true,
-            "url": "http://localhost:1050/signup",
+            "url": "http://localhost:1050/login",
             "webRoot": "${workspaceFolder}",
         },
         {
diff --git a/src/client/SocketStub.ts b/src/client/SocketStub.ts
index 18df4ca0a..c48f21f63 100644
--- a/src/client/SocketStub.ts
+++ b/src/client/SocketStub.ts
@@ -48,6 +48,7 @@ export class SocketStub {
 
     public static SEND_FIELDS_REQUEST(fieldIds: FieldId[], callback: (fields: { [key: string]: Field }) => any) {
         Utils.EmitCallback(Server.Socket, MessageStore.GetFields, fieldIds, (fields: any[]) => {
+            console.log(fieldIds);
             let fieldMap: any = {};
             for (let field of fields) {
                 fieldMap[field._id] = ServerUtils.FromJson(field);
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 1d24ff7d2..596652cf0 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -44,14 +44,14 @@ export namespace Documents {
     const collProtoId = "collectionProto";
     const kvpProtoId = "kvpProto";
 
-    export function initProtos(mainDocId: string, callback: (mainDoc?: Document) => void) {
-        Server.GetFields([collProtoId, textProtoId, imageProtoId, mainDocId], (fields) => {
+    export function initProtos(callback: () => void) {
+        Server.GetFields([collProtoId, textProtoId, imageProtoId], (fields) => {
             collProto = fields[collProtoId] as Document;
             imageProto = fields[imageProtoId] as Document;
             textProto = fields[textProtoId] as Document;
             webProto = fields[webProtoId] as Document;
             kvpProto = fields[kvpProtoId] as Document;
-            callback(fields[mainDocId] as Document)
+            callback();
         });
     }
     function assignOptions(doc: Document, options: DocumentOptions): Document {
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 2f4264ad9..da7e17f1f 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -19,13 +19,14 @@ import { DocumentDecorations } from './DocumentDecorations';
 import { DocumentView } from './nodes/DocumentView';
 import "./Main.scss";
 import { observer } from 'mobx-react';
+import { Field, Opt } from '../../fields/Field';
 
 @observer
 export class Main extends React.Component {
     // dummy initializations keep the compiler happy
-    @observable private mainDocId = "";
-    @observable private mainContainer: Document = new Document;
-    @observable private mainfreeform: Document = new Document;
+    @observable private mainContainer?: Document;
+    @observable private mainfreeform?: Document;
+    @observable private userWorkspaces: Document[] = [];
 
     constructor(props: Readonly<{}>) {
         super(props);
@@ -33,7 +34,9 @@ export class Main extends React.Component {
         configure({ enforceActions: "observed" });
 
         this.initEventListeners();
-        this.initAuthenticationRouters();
+        Documents.initProtos(() => {
+            this.initAuthenticationRouters();
+        });
     }
 
     initEventListeners = () => {
@@ -50,46 +53,49 @@ export class Main extends React.Component {
     initAuthenticationRouters = () => {
         // Load the user's active workspace, or create a new one if initial session after signup
         request.get(this.contextualize("getActiveWorkspaceId"), (error, response, body) => {
-            this.requestWorkspace(body ? body : this.getNewWorkspace());
+            if (body) {
+                Server.GetField(body, field => {
+                    if (field instanceof Document) {
+                        this.openDocument(field);
+                    } else {
+                        this.createNewWorkspace();
+                    }
+                });
+            } else {
+                this.createNewWorkspace();
+            }
         });
     }
 
-    getNewWorkspace = (): string => {
-        let newId = Utils.GenerateGuid();
+    @action
+    createNewWorkspace = (): void => {
+        let mainDoc = Documents.DockDocument(JSON.stringify({ content: [{ type: 'row', content: [] }] }), { title: "main container" });
+        let newId = mainDoc.Id;
         request.post(this.contextualize("addWorkspaceId"), {
             body: { target: newId },
             json: true
-        })
-        return newId;
+        });
+
+        // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
+        setTimeout(() => {
+            let freeformDoc = Documents.FreeformDocument([], { x: 0, y: 400, title: "mini collection" });
+
+            var dockingLayout = { content: [{ type: 'row', content: [CollectionDockingView.makeDocumentConfig(freeformDoc)] }] };
+            mainDoc.SetText(KeyStore.Data, JSON.stringify(dockingLayout));
+            mainDoc.Set(KeyStore.ActiveFrame, freeformDoc);
+            this.openDocument(mainDoc);
+        }, 0);
+        this.userWorkspaces.push(mainDoc);
     }
 
     @action
-    requestWorkspace = (activeWorkspaceId: string) => {
+    openDocument = (doc: Document): void => {
         request.post(this.contextualize("setActiveWorkspaceId"), {
-            body: { target: activeWorkspaceId },
+            body: { target: doc.Id },
             json: true
-        })
-        Documents.initProtos(activeWorkspaceId, this.prepareWorkspace);
-    }
-
-    @action.bound
-    prepareWorkspace = (res?: Document) => {
-        if (res instanceof Document) {
-            this.mainContainer = res;
-            this.mainContainer.GetAsync(KeyStore.ActiveFrame, field => this.mainfreeform = field as Document);
-        }
-        else {
-            this.mainContainer = Documents.DockDocument(JSON.stringify({ content: [{ type: 'row', content: [] }] }), { title: "main container" }, this.mainDocId);
-
-            // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
-            setTimeout(() => {
-                this.mainfreeform = Documents.FreeformDocument([], { x: 0, y: 400, title: "mini collection" });
-
-                var dockingLayout = { content: [{ type: 'row', content: [CollectionDockingView.makeDocumentConfig(this.mainfreeform)] }] };
-                this.mainContainer.SetText(KeyStore.Data, JSON.stringify(dockingLayout));
-                this.mainContainer.Set(KeyStore.ActiveFrame, this.mainfreeform);
-            }, 0);
-        }
+        });
+        this.mainContainer = doc;
+        this.mainContainer.GetAsync(KeyStore.ActiveFrame, field => this.mainfreeform = field as Document);
     }
 
     toggleWorkspaces = () => {
@@ -117,8 +123,11 @@ export class Main extends React.Component {
         let addImageNode = action(() => Documents.ImageDocument(imgurl, { width: 200, height: 200, title: "an image of a cat" }));
         let addWebNode = action(() => Documents.WebDocument(weburl, { width: 200, height: 200, title: "a sample web page" }));
 
-        let addClick = (creator: () => Document) => action(() => this.mainfreeform.GetList<Document>(KeyStore.Data, []).push(creator()));
+        let addClick = (creator: () => Document) => action(() => this.mainfreeform!.GetList<Document>(KeyStore.Data, []).push(creator()));
 
+        if (!this.mainContainer) {
+            return <div></div>
+        }
         return (
             <div style={{ position: "absolute", width: "100%", height: "100%" }}>
                 <DocumentView Document={this.mainContainer}
@@ -131,7 +140,7 @@ export class Main extends React.Component {
                     ContainingCollectionView={undefined} />
                 <DocumentDecorations />
                 <ContextMenu />
-                <WorkspacesMenu active={this.mainDocId} load={this.requestWorkspace} new={this.getNewWorkspace} />
+                <WorkspacesMenu active={this.mainContainer} open={this.openDocument} new={this.createNewWorkspace} allWorkspaces={this.userWorkspaces} />
                 <div className="main-buttonDiv" style={{ bottom: '0px' }} ref={imgRef} >
                     <button onPointerDown={setupDrag(imgRef, addImageNode)} onClick={addClick(addImageNode)}>Add Image</button></div>
                 <div className="main-buttonDiv" style={{ bottom: '25px' }} ref={webRef} >
diff --git a/src/server/authentication/controllers/WorkspacesMenu.tsx b/src/server/authentication/controllers/WorkspacesMenu.tsx
index b565af193..ebc4f5a10 100644
--- a/src/server/authentication/controllers/WorkspacesMenu.tsx
+++ b/src/server/authentication/controllers/WorkspacesMenu.tsx
@@ -4,62 +4,37 @@ import { observable, action, configure, reaction, computed, ObservableMap, runIn
 import { observer } from "mobx-react";
 import * as request from 'request'
 import './WorkspacesMenu.css'
+import { Document } from '../../../fields/Document';
+import { Server } from '../../../client/Server';
+import { Field } from '../../../fields/Field';
 
 export interface WorkspaceMenuProps {
-    active: string;
-    load: (workspaceId: string) => void;
-    new: () => string;
+    active: Document;
+    open: (workspace: Document) => void;
+    new: () => void;
+    allWorkspaces: Document[];
 }
 
 @observer
 export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> {
     static Instance: WorkspacesMenu;
     @observable private workspacesExposed: boolean = false;
-    @observable private workspaceIds: Array<string> = [];
-    @observable private selectedWorkspaceId: string = "";
 
     constructor(props: WorkspaceMenuProps) {
         super(props);
         WorkspacesMenu.Instance = this;
-        this.loadExistingWorkspace = this.loadExistingWorkspace.bind(this);
         this.addNewWorkspace = this.addNewWorkspace.bind(this);
-        this.selectedWorkspaceId = this.props.active;
     }
 
     @action
     addNewWorkspace() {
-        let newId = this.props.new();
-        this.selectedWorkspaceId = newId;
-        this.props.load(newId);
+        this.props.new();
         this.toggle();
     }
 
-    @action
-    loadExistingWorkspace = (e: React.MouseEvent<HTMLLIElement, MouseEvent>) => {
-        let id = e.currentTarget.innerHTML;
-        this.props.load(id);
-        this.selectedWorkspaceId = id;
-    }
-
     @action
     toggle() {
-        if (this.workspacesExposed) {
-            this.workspacesExposed = !this.workspacesExposed;
-        } else {
-            request.get(window.location.origin + "/getAllWorkspaceIds", this.idCallback)
-        }
-    }
-
-    @action.bound
-    idCallback: request.RequestCallback = (error, response, body) => {
-        this.workspaceIds = [];
-        let ids: Array<string> = JSON.parse(body) as Array<string>;
-        if (ids) {
-            for (let i = 0; i < ids.length; i++) {
-                this.workspaceIds.push(ids[i]);
-            }
-            this.workspacesExposed = !this.workspacesExposed;
-        }
+        this.workspacesExposed = !this.workspacesExposed;
     }
 
     render() {
@@ -78,8 +53,7 @@ export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> {
                     transition: "all 1s ease",
                     zIndex: 15,
                     padding: 10,
-                }}
-            >
+                }}>
                 <img
                     src="https://bit.ly/2IBBkxk"
                     style={{
@@ -90,16 +64,16 @@ export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> {
                     }}
                     onClick={this.addNewWorkspace}
                 />
-                {this.workspaceIds.map(s =>
+                {this.props.allWorkspaces.map(s =>
                     <li className={"ids"}
-                        key={s}
+                        key={s.Id}
                         style={{
                             listStyleType: "none",
-                            color: s === this.selectedWorkspaceId ? "darkblue" : "black",
+                            color: s.Id === this.props.active.Id ? "darkblue" : "black",
                             cursor: "grab"
                         }}
-                        onClick={this.loadExistingWorkspace}
-                    >{s}</li>
+                        onClick={() => this.props.open(s)}
+                    >{s.Title}</li>
                 )}
             </div>
         );
diff --git a/src/server/database.ts b/src/server/database.ts
index 07c5819ab..1553dd94e 100644
--- a/src/server/database.ts
+++ b/src/server/database.ts
@@ -70,6 +70,16 @@ export class Database {
             let collection = this.db.collection('documents');
             let cursor = collection.find({ _id: { "$in": ids } })
             cursor.toArray((err, docs) => {
+                if (err) {
+                    console.log("Error");
+                    console.log(err.message);
+                    console.log(err.errmsg);
+                    console.log(ids);
+                    console.log(["afca93a8-c6bd-4b58-967e-07784c5b12c8"]);
+                    console.log("MAKES SENSE: " + (ids instanceof Array));
+                }
+                console.log(typeof ids);
+                console.log("DATABASE: " + docs);
                 fn(docs);
             })
         };
diff --git a/src/server/index.ts b/src/server/index.ts
index e6f08bc29..40e1f6686 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -80,60 +80,58 @@ app.use((req, res, next) => {
 
 // AUTHENTICATION ROUTING
 
+enum Method {
+    Get,
+    Post
+}
+
+function addSecureRoute(method: Method,
+    route: string,
+    handler: (user: DashUserModel, req: express.Request, res: express.Response) => void,
+    nope: (res: express.Response) => any) {
+    route = "/" + route;
+    switch (method) {
+        case Method.Get:
+            app.get(route, (req, res) => {
+                const dashUser: DashUserModel = req.user;
+                if (!dashUser) return nope(res);
+                handler(dashUser, req, res);
+            });
+            break;
+        case Method.Post:
+            app.post(route, (req, res) => {
+                const dashUser: DashUserModel = req.user;
+                if (!dashUser) return nope(res);
+                handler(dashUser, req, res);
+            });
+            break;
+    }
+}
+
 // ***
 // Look for the definitions of these get and post
 // functions in the exports of user.ts
 
-// /home defines destination after a successful log in
-app.get("/home", (req, res) => {
-    // if user is not logged in, redirect to log in page
-    const dashUser: DashUserModel = req.user;
-    if (!dashUser) {
-        return res.redirect("/login");
-    }
-    // otherwise, connect them to Dash
-    // TODO: store and manage users' workspaces
-    // if (dashUser.allWorkspaceIds.length > 0) {
-    //     if (!dashUser.didSelectSessionWorkspace) {
-    //         return res.redirect("/workspaces");
-    //     }
-    // }
+addSecureRoute(Method.Get, "home", (user, req, res) => {
     res.sendFile(path.join(__dirname, '../../deploy/index.html'));
-});
-
-// app.get("/workspaces", getWorkspaces);
+}, res => res.redirect("/login"))
 
-app.get("/getActiveWorkspaceId", (req, res) => {
-    const dashUser: DashUserModel = req.user;
-    if (!dashUser) {
-        return;
-    }
-    res.send(dashUser.activeWorkspaceId || "");
-});
+addSecureRoute(Method.Get, "getActiveWorkspaceId", (user, req, res) => {
+    console.log(`/getActiveWorkspaceId in index.ts ${user.activeWorkspaceId}`);
+    res.send(user.activeWorkspaceId || "");
+}, () => { });
 
-app.get("/getAllWorkspaceIds", (req, res) => {
-    const dashUser: DashUserModel = req.user;
-    if (!dashUser) {
-        return;
-    }
-    res.send(JSON.stringify(dashUser.allWorkspaceIds as Array<String>));
-})
+addSecureRoute(Method.Get, "getAllWorkspaceIds", (user, req, res) => {
+    res.send(JSON.stringify(user.allWorkspaceIds as Array<String>));
+}, () => { });
 
-app.post("/setActiveWorkspaceId", (req, res) => {
-    const dashUser: DashUserModel = req.user;
-    if (!dashUser) {
-        return;
-    }
-    dashUser.update({ $set: { activeWorkspaceId: req.body.target } }, () => { });
-})
+addSecureRoute(Method.Post, "setActiveWorkspaceId", (user, req) => {
+    user.update({ $set: { activeWorkspaceId: req.body.target } }, () => { });
+}, () => { });
 
-app.post("/addWorkspaceId", (req, res) => {
-    const dashUser: DashUserModel = req.user;
-    if (!dashUser) {
-        return;
-    }
-    dashUser.update({ $push: { allWorkspaceIds: req.body.target } }, () => { });
-})
+addSecureRoute(Method.Post, "addWorkspaceId", (user, req) => {
+    user.update({ $push: { allWorkspaceIds: req.body.target } }, () => { });
+}, () => { });
 
 // anyone attempting to navigate to localhost at this port will
 // first have to login
-- 
cgit v1.2.3-70-g09d2


From 8ea26fc316685f0a3d1b81b7c2e8bd612acbb99c Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Fri, 8 Mar 2019 23:42:40 -0500
Subject: workspace persistencegit add -Agit add -A

---
 src/client/views/Main.tsx                                | 11 ++++++++++-
 src/client/views/nodes/DocumentView.tsx                  |  2 +-
 src/server/authentication/controllers/WorkspacesMenu.tsx | 14 ++++++++++----
 src/server/index.ts                                      |  1 -
 4 files changed, 21 insertions(+), 7 deletions(-)

(limited to 'src/server/authentication/controllers/WorkspacesMenu.tsx')

diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index da7e17f1f..cb13e172e 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -35,6 +35,11 @@ export class Main extends React.Component {
 
         this.initEventListeners();
         Documents.initProtos(() => {
+            // retrieve all workspace documents from the server
+            request.get(this.contextualize("getAllWorkspaceIds"), (error, res, body) => {
+                let ids = JSON.parse(body) as string[];
+                Server.GetFields(ids, action((fields: { [id: string]: Field }) => this.userWorkspaces = ids.map(id => fields[id] as Document)));
+            })
             this.initAuthenticationRouters();
         });
     }
@@ -54,6 +59,7 @@ export class Main extends React.Component {
         // Load the user's active workspace, or create a new one if initial session after signup
         request.get(this.contextualize("getActiveWorkspaceId"), (error, response, body) => {
             if (body) {
+                console.log("FROM THE TOP, SOMEONE'S ALREADY BEEN HERE");
                 Server.GetField(body, field => {
                     if (field instanceof Document) {
                         this.openDocument(field);
@@ -62,6 +68,7 @@ export class Main extends React.Component {
                     }
                 });
             } else {
+                console.log("FROM THE TOP, WE THINK THERE'S NO CURRENT USER");
                 this.createNewWorkspace();
             }
         });
@@ -69,7 +76,7 @@ export class Main extends React.Component {
 
     @action
     createNewWorkspace = (): void => {
-        let mainDoc = Documents.DockDocument(JSON.stringify({ content: [{ type: 'row', content: [] }] }), { title: "main container" });
+        let mainDoc = Documents.DockDocument(JSON.stringify({ content: [{ type: 'row', content: [] }] }), { title: `Main Container ${this.userWorkspaces.length}` });
         let newId = mainDoc.Id;
         request.post(this.contextualize("addWorkspaceId"), {
             body: { target: newId },
@@ -86,6 +93,7 @@ export class Main extends React.Component {
             this.openDocument(mainDoc);
         }, 0);
         this.userWorkspaces.push(mainDoc);
+        console.log(this.userWorkspaces.length);
     }
 
     @action
@@ -94,6 +102,7 @@ export class Main extends React.Component {
             body: { target: doc.Id },
             json: true
         });
+        console.log(`OPENING ${doc.Id}`);
         this.mainContainer = doc;
         this.mainContainer.GetAsync(KeyStore.ActiveFrame, field => this.mainfreeform = field as Document);
     }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 19a455b74..0052e9316 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -212,7 +212,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         SelectionManager.SelectDoc(this, e.ctrlKey);
     }
 
-    @computed get mainContent() {
+    get mainContent() {
         return <JsxParser
             components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValueBox }}
             bindings={this._documentBindings}
diff --git a/src/server/authentication/controllers/WorkspacesMenu.tsx b/src/server/authentication/controllers/WorkspacesMenu.tsx
index ebc4f5a10..00de34d7a 100644
--- a/src/server/authentication/controllers/WorkspacesMenu.tsx
+++ b/src/server/authentication/controllers/WorkspacesMenu.tsx
@@ -46,20 +46,23 @@ export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> {
                     height: "auto",
                     borderRadius: 5,
                     position: "absolute",
-                    top: 50,
-                    left: this.workspacesExposed ? 8 : -500,
+                    top: 55,
+                    left: this.workspacesExposed ? 11 : -500,
                     background: "white",
                     border: "black solid 2px",
                     transition: "all 1s ease",
                     zIndex: 15,
                     padding: 10,
+                    paddingRight: 12,
                 }}>
                 <img
                     src="https://bit.ly/2IBBkxk"
                     style={{
                         width: 20,
                         height: 20,
-                        marginBottom: 10,
+                        marginTop: 3,
+                        marginLeft: 3,
+                        marginBottom: 3,
                         cursor: "grab"
                     }}
                     onClick={this.addNewWorkspace}
@@ -72,7 +75,10 @@ export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> {
                             color: s.Id === this.props.active.Id ? "darkblue" : "black",
                             cursor: "grab"
                         }}
-                        onClick={() => this.props.open(s)}
+                        onClick={() => {
+                            this.props.open(s);
+                            console.log(this.props.allWorkspaces.length);
+                        }}
                     >{s.Title}</li>
                 )}
             </div>
diff --git a/src/server/index.ts b/src/server/index.ts
index 40e1f6686..3e0c28f14 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -117,7 +117,6 @@ addSecureRoute(Method.Get, "home", (user, req, res) => {
 }, res => res.redirect("/login"))
 
 addSecureRoute(Method.Get, "getActiveWorkspaceId", (user, req, res) => {
-    console.log(`/getActiveWorkspaceId in index.ts ${user.activeWorkspaceId}`);
     res.send(user.activeWorkspaceId || "");
 }, () => { });
 
-- 
cgit v1.2.3-70-g09d2


From e673d4f70b8feb37dcd328440c019a49f8a22e88 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Sat, 9 Mar 2019 16:27:24 -0500
Subject: Fixed slight bug with timing of workspace retrieval

---
 src/client/views/Main.tsx                          | 22 +++++++++++-----------
 .../authentication/controllers/WorkspacesMenu.tsx  |  4 ++--
 2 files changed, 13 insertions(+), 13 deletions(-)

(limited to 'src/server/authentication/controllers/WorkspacesMenu.tsx')

diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index cb13e172e..b160a7671 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -35,11 +35,6 @@ export class Main extends React.Component {
 
         this.initEventListeners();
         Documents.initProtos(() => {
-            // retrieve all workspace documents from the server
-            request.get(this.contextualize("getAllWorkspaceIds"), (error, res, body) => {
-                let ids = JSON.parse(body) as string[];
-                Server.GetFields(ids, action((fields: { [id: string]: Field }) => this.userWorkspaces = ids.map(id => fields[id] as Document)));
-            })
             this.initAuthenticationRouters();
         });
     }
@@ -59,34 +54,39 @@ export class Main extends React.Component {
         // Load the user's active workspace, or create a new one if initial session after signup
         request.get(this.contextualize("getActiveWorkspaceId"), (error, response, body) => {
             if (body) {
-                console.log("FROM THE TOP, SOMEONE'S ALREADY BEEN HERE");
                 Server.GetField(body, field => {
                     if (field instanceof Document) {
                         this.openDocument(field);
                     } else {
-                        this.createNewWorkspace();
+                        this.createNewWorkspace(true);
                     }
                 });
             } else {
-                console.log("FROM THE TOP, WE THINK THERE'S NO CURRENT USER");
-                this.createNewWorkspace();
+                this.createNewWorkspace(true);
             }
         });
     }
 
     @action
-    createNewWorkspace = (): void => {
+    createNewWorkspace = (init: boolean): void => {
         let mainDoc = Documents.DockDocument(JSON.stringify({ content: [{ type: 'row', content: [] }] }), { title: `Main Container ${this.userWorkspaces.length}` });
         let newId = mainDoc.Id;
         request.post(this.contextualize("addWorkspaceId"), {
             body: { target: newId },
             json: true
+        }, () => {
+            if (init) {
+                // retrieve all workspace documents from the server
+                request.get(this.contextualize("getAllWorkspaceIds"), (error, res, body) => {
+                    let ids = JSON.parse(body) as string[];
+                    Server.GetFields(ids, action((fields: { [id: string]: Field }) => this.userWorkspaces = ids.map(id => fields[id] as Document)));
+                });
+            }
         });
 
         // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
         setTimeout(() => {
             let freeformDoc = Documents.FreeformDocument([], { x: 0, y: 400, title: "mini collection" });
-
             var dockingLayout = { content: [{ type: 'row', content: [CollectionDockingView.makeDocumentConfig(freeformDoc)] }] };
             mainDoc.SetText(KeyStore.Data, JSON.stringify(dockingLayout));
             mainDoc.Set(KeyStore.ActiveFrame, freeformDoc);
diff --git a/src/server/authentication/controllers/WorkspacesMenu.tsx b/src/server/authentication/controllers/WorkspacesMenu.tsx
index 00de34d7a..70c37774c 100644
--- a/src/server/authentication/controllers/WorkspacesMenu.tsx
+++ b/src/server/authentication/controllers/WorkspacesMenu.tsx
@@ -11,7 +11,7 @@ import { Field } from '../../../fields/Field';
 export interface WorkspaceMenuProps {
     active: Document;
     open: (workspace: Document) => void;
-    new: () => void;
+    new: (init: boolean) => void;
     allWorkspaces: Document[];
 }
 
@@ -28,7 +28,7 @@ export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> {
 
     @action
     addNewWorkspace() {
-        this.props.new();
+        this.props.new(false);
         this.toggle();
     }
 
-- 
cgit v1.2.3-70-g09d2


From 81c0a8373fd5cb051531762243e200f11f8c7297 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Sat, 9 Mar 2019 23:00:41 -0500
Subject: editable workspace titles now supported, added 'display' prop to
 EditableView

---
 src/client/views/EditableView.tsx                  |  5 ++--
 .../views/collections/CollectionSchemaView.tsx     |  6 ++--
 .../views/collections/CollectionTreeView.tsx       |  5 +++-
 .../authentication/controllers/WorkspacesMenu.tsx  | 32 +++++++++++++++-------
 4 files changed, 33 insertions(+), 15 deletions(-)

(limited to 'src/server/authentication/controllers/WorkspacesMenu.tsx')

diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 84b1b91c3..55a49863d 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -20,6 +20,7 @@ export interface EditableProps {
      */
     contents: any;
     height: number
+    display: string;
 }
 
 /**
@@ -46,10 +47,10 @@ export class EditableView extends React.Component<EditableProps> {
     render() {
         if (this.editing) {
             return <input defaultValue={this.props.GetValue()} onKeyDown={this.onKeyDown} autoFocus onBlur={action(() => this.editing = false)}
-                style={{ display: "inline" }}></input>
+                style={{ display: this.props.display }}></input>
         } else {
             return (
-                <div className="editableView-container-editing" style={{ display: "inline", height: "100%", maxHeight: `${this.props.height}` }}
+                <div className="editableView-container-editing" style={{ display: this.props.display, height: "100%", maxHeight: `${this.props.height}` }}
                     onClick={action(() => this.editing = true)}>
                     {this.props.contents}
                 </div>
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 49f95c014..2868e1322 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -50,7 +50,9 @@ export class CollectionSchemaView extends CollectionViewBase {
         let onItemDown = setupDrag(reference, () => props.doc);
         return (
             <div onPointerDown={onItemDown} key={props.doc.Id} ref={reference}>
-                <EditableView contents={contents}
+                <EditableView
+                    display={"inline"}
+                    contents={contents}
                     height={36} GetValue={() => {
                         let field = props.doc.Get(props.fieldKey);
                         if (field && field instanceof Field) {
@@ -59,7 +61,7 @@ export class CollectionSchemaView extends CollectionViewBase {
                         return field || "";
                     }}
                     SetValue={(value: string) => {
-                        let script = CompileScript(value, undefined, true);
+                        let script = CompileScript(value);
                         if (!script.compiled) {
                             return false;
                         }
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 8b06d9ac4..9c31bdae2 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -69,7 +69,9 @@ class TreeView extends React.Component<TreeViewProps> {
             return <div key={this.props.document.Id}></div>;
         }
 
-        return <div className="docContainer"> <EditableView contents={title.Data}
+        return <div className="docContainer"> <EditableView
+            display={"inline"}
+            contents={title.Data}
             height={36} GetValue={() => {
                 let title = this.props.document.GetT<TextField>(KeyStore.Title, TextField);
                 if (title && title !== "<Waiting>")
@@ -159,6 +161,7 @@ export class CollectionTreeView extends CollectionViewBase {
             <div id="body" className="collectionTreeView-dropTarget" onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget} style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }}>
                 <h3>
                     <EditableView contents={titleStr}
+                        display={"inline"}
                         height={72} GetValue={() => {
                             return this.props.Document.Title;
                         }} SetValue={(value: string) => {
diff --git a/src/server/authentication/controllers/WorkspacesMenu.tsx b/src/server/authentication/controllers/WorkspacesMenu.tsx
index 70c37774c..ffef2e11c 100644
--- a/src/server/authentication/controllers/WorkspacesMenu.tsx
+++ b/src/server/authentication/controllers/WorkspacesMenu.tsx
@@ -7,6 +7,8 @@ import './WorkspacesMenu.css'
 import { Document } from '../../../fields/Document';
 import { Server } from '../../../client/Server';
 import { Field } from '../../../fields/Field';
+import { EditableView } from '../../../client/views/EditableView';
+import { KeyStore } from '../../../fields/KeyStore';
 
 export interface WorkspaceMenuProps {
     active: Document;
@@ -67,19 +69,29 @@ export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> {
                     }}
                     onClick={this.addNewWorkspace}
                 />
-                {this.props.allWorkspaces.map(s =>
-                    <li className={"ids"}
+                {this.props.allWorkspaces.map((s, i) =>
+                    <div
                         key={s.Id}
-                        style={{
-                            listStyleType: "none",
-                            color: s.Id === this.props.active.Id ? "darkblue" : "black",
-                            cursor: "grab"
-                        }}
-                        onClick={() => {
+                        onContextMenu={(e) => {
+                            e.preventDefault();
                             this.props.open(s);
-                            console.log(this.props.allWorkspaces.length);
                         }}
-                    >{s.Title}</li>
+                        style={{
+                            marginTop: 10
+                        }}
+                    >
+                        <span>{i + 1} - </span>
+                        <EditableView
+                            display={"inline"}
+                            GetValue={() => { return s.Title }}
+                            SetValue={(title: string): boolean => {
+                                s.SetText(KeyStore.Title, title);
+                                return true;
+                            }}
+                            contents={s.Title}
+                            height={20}
+                        />
+                    </div>
                 )}
             </div>
         );
-- 
cgit v1.2.3-70-g09d2


From bece3110a3d6fa18dd89415a5e636c6792aea4e1 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Wed, 20 Mar 2019 05:07:52 -0400
Subject: Refactored users to have a single user document instead of a list of
 workspaces

---
 src/client/views/Main.tsx                          | 132 ++++++++++++---------
 src/fields/KeyStore.ts                             |   2 +
 src/mobile/ImageUpload.tsx                         |  38 +++---
 src/server/RouteStore.ts                           |   5 +-
 .../authentication/controllers/WorkspacesMenu.tsx  |  19 +--
 .../authentication/controllers/user_controller.ts  |   3 +-
 .../authentication/models/current_user_utils.ts    |  46 +++++--
 src/server/authentication/models/user_model.ts     |  11 +-
 src/server/index.ts                                |  33 +-----
 9 files changed, 144 insertions(+), 145 deletions(-)

(limited to 'src/server/authentication/controllers/WorkspacesMenu.tsx')

diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index ac51a7d87..a1a6cc475 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -8,6 +8,7 @@ import "./Main.scss";
 import { MessageStore } from '../../server/Message';
 import { Utils } from '../../Utils';
 import * as request from 'request'
+import * as rp from 'request-promise'
 import { Documents } from '../documents/Documents';
 import { Server } from '../Server';
 import { setupDrag } from '../util/DragManager';
@@ -40,7 +41,7 @@ import Measure from 'react-measure';
 import { DashUserModel } from '../../server/authentication/models/user_model';
 import { ServerUtils } from '../../server/ServerUtil';
 import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
-import { Field, Opt } from '../../fields/Field';
+import { Field, Opt, FieldWaiting } from '../../fields/Field';
 import { ListField } from '../../fields/ListField';
 import { map } from 'bluebird';
 import { Gateway, Settings } from '../northstar/manager/Gateway';
@@ -49,13 +50,26 @@ import { Catalog } from '../northstar/model/idea/idea';
 @observer
 export class Main extends React.Component {
     // dummy initializations keep the compiler happy
-    @observable private mainContainer?: Document;
     @observable private mainfreeform?: Document;
-    @observable private userWorkspaces: Document[] = [];
     @observable public pwidth: number = 0;
     @observable public pheight: number = 0;
     @observable private _northstarCatalog: Catalog | undefined = undefined;
 
+    @computed private get mainContainer(): Document | undefined {
+        let doc = this.userDocument.GetT(KeyStore.ActiveWorkspace, Document);
+        return doc == FieldWaiting ? undefined : doc;
+    }
+
+    private set mainContainer(doc: Document | undefined) {
+        if (doc) {
+            this.userDocument.Set(KeyStore.ActiveWorkspace, doc);
+        }
+    }
+
+    private get userDocument(): Document {
+        return CurrentUserUtils.UserDocument;
+    }
+
     public mainDocId: string | undefined;
     private currentUser?: DashUserModel;
     public static Instance: Main;
@@ -67,12 +81,12 @@ export class Main extends React.Component {
         configure({ enforceActions: "observed" });
         if (window.location.pathname !== RouteStore.home) {
             let pathname = window.location.pathname.split("/");
-            this.mainDocId = pathname[pathname.length - 1];
+            if (pathname.length > 1 && pathname[pathname.length - 2] == 'doc') {
+                this.mainDocId = pathname[pathname.length - 1];
+            }
         };
 
-        this.initializeNorthstar();
-
-        CurrentUserUtils.loadCurrentUser();
+        // this.initializeNorthstar();
 
         library.add(faFont);
         library.add(faImage);
@@ -143,63 +157,50 @@ export class Main extends React.Component {
 
     initAuthenticationRouters = () => {
         // Load the user's active workspace, or create a new one if initial session after signup
-        request.get(ServerUtils.prepend(RouteStore.getActiveWorkspace), (error, response, body) => {
-            if (this.mainDocId || body) {
-                Server.GetField(this.mainDocId || body, field => {
-                    if (field instanceof Document) {
-                        this.openWorkspace(field);
-                        this.populateWorkspaces();
-                    } else {
-                        this.createNewWorkspace(true, this.mainDocId);
-                    }
-                });
-            } else {
-                this.createNewWorkspace(true, this.mainDocId);
-            }
-        });
-    }
-
-    @action
-    createNewWorkspace = (init: boolean, id?: string): void => {
-        let mainDoc = Documents.DockDocument(JSON.stringify({ content: [{ type: 'row', content: [] }] }), { title: `Main Container ${this.userWorkspaces.length + 1}` }, id);
-        let newId = mainDoc.Id;
-        request.post(ServerUtils.prepend(RouteStore.addWorkspace), {
-            body: { target: newId },
-            json: true
-        }, () => { if (init) this.populateWorkspaces(); });
-
-        // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
-        setTimeout(() => {
-            let freeformDoc = Documents.FreeformDocument([], { x: 0, y: 400, title: "mini collection" });
-            var dockingLayout = { content: [{ type: 'row', content: [CollectionDockingView.makeDocumentConfig(freeformDoc)] }] };
-            mainDoc.SetText(KeyStore.Data, JSON.stringify(dockingLayout));
-            mainDoc.Set(KeyStore.ActiveFrame, freeformDoc);
-            this.openWorkspace(mainDoc);
-            let pendingDocument = Documents.SchemaDocument([], { title: "New Mobile Uploads" })
-            mainDoc.Set(KeyStore.OptionalRightCollection, pendingDocument);
-        }, 0);
-        this.userWorkspaces.push(mainDoc);
+        if (!this.mainDocId) {
+            this.userDocument.GetTAsync(KeyStore.ActiveWorkspace, Document).then(doc => {
+                if (doc) {
+                    this.openWorkspace(doc);
+                } else {
+                    this.createNewWorkspace();
+                }
+            })
+        } else {
+            Server.GetField(this.mainDocId).then(field => {
+                if (field instanceof Document) {
+                    this.openWorkspace(field)
+                } else {
+                    this.createNewWorkspace(this.mainDocId);
+                }
+            })
+        }
     }
 
     @action
-    populateWorkspaces = () => {
-        // retrieve all workspace documents from the server
-        request.get(ServerUtils.prepend(RouteStore.getAllWorkspaces), (error, res, body) => {
-            let ids = JSON.parse(body) as string[];
-            Server.GetFields(ids, action((fields: { [id: string]: Field }) => this.userWorkspaces = ids.map(id => fields[id] as Document)));
-        });
+    createNewWorkspace = (id?: string): void => {
+        this.userDocument.GetTAsync<ListField<Document>>(KeyStore.Workspaces, ListField).then(action((list: Opt<ListField<Document>>) => {
+            if (list) {
+                let freeformDoc = Documents.FreeformDocument([], { x: 0, y: 400, title: "mini collection" });
+                var dockingLayout = { content: [{ type: 'row', content: [CollectionDockingView.makeDocumentConfig(freeformDoc)] }] };
+                let mainDoc = Documents.DockDocument(JSON.stringify(dockingLayout), { title: `Main Container ${list.Data.length + 1}` }, id);
+                list.Data.push(mainDoc);
+                // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
+                setTimeout(() => {
+                    mainDoc.Set(KeyStore.ActiveFrame, freeformDoc);
+                    this.openWorkspace(mainDoc);
+                    let pendingDocument = Documents.SchemaDocument([], { title: "New Mobile Uploads" })
+                    mainDoc.Set(KeyStore.OptionalRightCollection, pendingDocument);
+                }, 0);
+            }
+        }));
     }
 
     @action
     openWorkspace = (doc: Document, fromHistory = false): void => {
-        request.post(ServerUtils.prepend(RouteStore.setActiveWorkspace), {
-            body: { target: doc.Id },
-            json: true
-        });
         this.mainContainer = doc;
         fromHistory || window.history.pushState(null, doc.Title, "/doc/" + doc.Id);
         this.mainContainer.GetTAsync(KeyStore.ActiveFrame, Document, field => this.mainfreeform = field);
-        this.mainContainer.GetTAsync(KeyStore.OptionalRightCollection, Document, col => {
+        this.userDocument.GetTAsync(KeyStore.OptionalRightCollection, Document).then(col => {
             // if there is a pending doc, and it has new data, show it (syip: we use a timeout to prevent collection docking view from being uninitialized)
             setTimeout(() => {
                 if (col) {
@@ -213,10 +214,15 @@ export class Main extends React.Component {
         });
     }
 
+    @observable
+    workspacesShown: boolean = false;
+
+    areWorkspacesShown = () => {
+        return this.workspacesShown;
+    }
+    @action
     toggleWorkspaces = () => {
-        if (WorkspacesMenu.Instance) {
-            WorkspacesMenu.Instance.toggle()
-        }
+        this.workspacesShown = !this.workspacesShown;
     }
 
     screenToLocalTransform = () => Transform.Identity
@@ -310,6 +316,12 @@ export class Main extends React.Component {
     }
 
     render() {
+        let workspaceMenu: any = null;
+        let workspaces = this.userDocument.GetT<ListField<Document>>(KeyStore.Workspaces, ListField);
+        if (workspaces && workspaces !== FieldWaiting) {
+            workspaceMenu = <WorkspacesMenu active={this.mainContainer} open={this.openWorkspace} new={this.createNewWorkspace} allWorkspaces={workspaces.Data}
+                isShown={this.areWorkspacesShown} toggle={this.toggleWorkspaces} />
+        }
         return (
             <div id="main-div">
                 <Measure onResize={(r: any) => runInAction(() => {
@@ -326,11 +338,13 @@ export class Main extends React.Component {
                 <ContextMenu />
                 {this.nodesMenu}
                 {this.miscButtons}
-                <WorkspacesMenu active={this.mainContainer} open={this.openWorkspace} new={this.createNewWorkspace} allWorkspaces={this.userWorkspaces} />
+                {workspaceMenu}
                 <InkingControl />
             </div>
         );
     }
 }
 
-ReactDOM.render(<Main />, document.getElementById('root'));
+CurrentUserUtils.loadCurrentUser().then(() => {
+    ReactDOM.render(<Main />, document.getElementById('root'));
+});
diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts
index 68883d6f1..891caaa81 100644
--- a/src/fields/KeyStore.ts
+++ b/src/fields/KeyStore.ts
@@ -28,6 +28,7 @@ export namespace KeyStore {
     export const SchemaSplitPercentage = new Key("SchemaSplitPercentage");
     export const Caption = new Key("Caption");
     export const ActiveFrame = new Key("ActiveFrame");
+    export const ActiveWorkspace = new Key("ActiveWorkspace");
     export const DocumentText = new Key("DocumentText");
     export const LinkedToDocs = new Key("LinkedToDocs");
     export const LinkedFromDocs = new Key("LinkedFromDocs");
@@ -41,4 +42,5 @@ export namespace KeyStore {
     export const OptionalRightCollection = new Key("OptionalRightCollection");
     export const Archives = new Key("Archives");
     export const Updated = new Key("Updated");
+    export const Workspaces = new Key("Workspaces");
 }
diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx
index 16808a598..47b9d8f0b 100644
--- a/src/mobile/ImageUpload.tsx
+++ b/src/mobile/ImageUpload.tsx
@@ -7,7 +7,7 @@ import { Server } from '../client/Server';
 import { Documents } from '../client/documents/Documents';
 import { ListField } from '../fields/ListField';
 import { ImageField } from '../fields/ImageField';
-import request = require('request');
+import * as rp from 'request-promise'
 import { ServerUtils } from '../server/ServerUtil';
 import { RouteStore } from '../server/RouteStore';
 
@@ -40,28 +40,24 @@ const onFileLoad = (file: any) => {
                 json.map((file: any) => {
                     let path = window.location.origin + file
                     var doc: Document = Documents.ImageDocument(path, { nativeWidth: 200, width: 200 })
-                    doc.GetTAsync(KeyStore.Data, ImageField, (i) => {
-                        if (i) {
-                            document.getElementById("message")!.innerText = i.Data.href;
+
+                    rp.get(ServerUtils.prepend(RouteStore.getUserDocumentId)).then(res => {
+                        if (res) {
+                            return Server.GetField(res);
+                        }
+                        throw new Error("No user id returned");
+                    }).then(field => {
+                        if (field instanceof Document) {
+                            return field.GetTAsync(KeyStore.OptionalRightCollection, Document)
                         }
-                    })
-                    request.get(ServerUtils.prepend(RouteStore.getActiveWorkspace), (error, response, body) => {
-                        if (body) {
-                            Server.GetField(body, field => {
-                                if (field instanceof Document) {
-                                    field.GetTAsync(KeyStore.OptionalRightCollection, Document,
-                                        pending => {
-                                            if (pending) {
-                                                pending.GetOrCreateAsync(KeyStore.Data, ListField, list => {
-                                                    list.Data.push(doc);
-                                                })
-                                            }
-                                        })
-                                }
-                            }
-                            );
+                    }).then(pending => {
+                        if (pending) {
+                            pending.GetOrCreateAsync(KeyStore.Data, ListField, list => {
+                                list.Data.push(doc);
+                            })
                         }
-                    })
+                    });
+
                     // console.log(window.location.origin + file[0])
 
                     //imgPrev.setAttribute("src", window.location.origin + files[0].name)
diff --git a/src/server/RouteStore.ts b/src/server/RouteStore.ts
index fb06b878b..fdf5b6a5c 100644
--- a/src/server/RouteStore.ts
+++ b/src/server/RouteStore.ts
@@ -15,10 +15,7 @@ export enum RouteStore {
 
     // USER AND WORKSPACES
     getCurrUser = "/getCurrentUser",
-    addWorkspace = "/addWorkspaceId",
-    getAllWorkspaces = "/getAllWorkspaceIds",
-    getActiveWorkspace = "/getActiveWorkspaceId",
-    setActiveWorkspace = "/setActiveWorkspaceId",
+    getUserDocumentId = "/getUserDocumentId",
     updateCursor = "/updateCursor",
 
     openDocumentWithId = "/doc/:docId",
diff --git a/src/server/authentication/controllers/WorkspacesMenu.tsx b/src/server/authentication/controllers/WorkspacesMenu.tsx
index 1533b1e62..8e14cf98e 100644
--- a/src/server/authentication/controllers/WorkspacesMenu.tsx
+++ b/src/server/authentication/controllers/WorkspacesMenu.tsx
@@ -9,30 +9,23 @@ import { KeyStore } from '../../../fields/KeyStore';
 export interface WorkspaceMenuProps {
     active: Document | undefined;
     open: (workspace: Document) => void;
-    new: (init: boolean) => void;
+    new: () => void;
     allWorkspaces: Document[];
+    isShown: () => boolean;
+    toggle: () => void;
 }
 
 @observer
 export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> {
-    static Instance: WorkspacesMenu;
-    @observable private workspacesExposed: boolean = false;
-
     constructor(props: WorkspaceMenuProps) {
         super(props);
-        WorkspacesMenu.Instance = this;
         this.addNewWorkspace = this.addNewWorkspace.bind(this);
     }
 
     @action
     addNewWorkspace() {
-        this.props.new(false);
-        this.toggle();
-    }
-
-    @action
-    toggle() {
-        this.workspacesExposed = !this.workspacesExposed;
+        this.props.new();
+        this.props.toggle();
     }
 
     render() {
@@ -45,7 +38,7 @@ export class WorkspacesMenu extends React.Component<WorkspaceMenuProps> {
                     borderRadius: 5,
                     position: "absolute",
                     top: 78,
-                    left: this.workspacesExposed ? 11 : -500,
+                    left: this.props.isShown() ? 11 : -500,
                     background: "white",
                     border: "black solid 2px",
                     transition: "all 1s ease",
diff --git a/src/server/authentication/controllers/user_controller.ts b/src/server/authentication/controllers/user_controller.ts
index 2cef958e8..e365b8dce 100644
--- a/src/server/authentication/controllers/user_controller.ts
+++ b/src/server/authentication/controllers/user_controller.ts
@@ -11,6 +11,7 @@ import * as async from 'async';
 import * as nodemailer from 'nodemailer';
 import c = require("crypto");
 import { RouteStore } from "../../RouteStore";
+import { Utils } from "../../../Utils";
 
 /**
  * GET /signup
@@ -54,7 +55,7 @@ export let postSignup = (req: Request, res: Response, next: NextFunction) => {
     const user = new User({
         email,
         password,
-        userDoc: "document here"
+        userDocumentId: Utils.GenerateGuid()
     });
 
     User.findOne({ email }, (err, existingUser) => {
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index cc433eb73..17a6d493b 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -1,29 +1,61 @@
 import { DashUserModel } from "./user_model";
-import * as request from 'request'
+import * as rp from 'request-promise';
 import { RouteStore } from "../../RouteStore";
 import { ServerUtils } from "../../ServerUtil";
+import { Server } from "../../../client/Server";
+import { Document } from "../../../fields/Document";
+import { KeyStore } from "../../../fields/KeyStore";
+import { ListField } from "../../../fields/ListField";
+import { Documents } from "../../../client/documents/Documents";
 
 export class CurrentUserUtils {
     private static curr_email: string;
     private static curr_id: string;
+    private static user_document: Document;
 
-    public static get email() {
+    public static get email(): string {
         return CurrentUserUtils.curr_email;
     }
 
-    public static get id() {
+    public static get id(): string {
         return CurrentUserUtils.curr_id;
     }
 
-    public static loadCurrentUser() {
-        request.get(ServerUtils.prepend(RouteStore.getCurrUser), (error, response, body) => {
-            if (body) {
-                let obj = JSON.parse(body);
+    public static get UserDocument(): Document {
+        return CurrentUserUtils.user_document;
+    }
+
+    private static createUserDocument(id: string): Document {
+        let doc = new Document(id);
+
+        doc.Set(KeyStore.Workspaces, new ListField<Document>());
+        doc.Set(KeyStore.OptionalRightCollection, Documents.SchemaDocument([], { title: "Pending documents" }))
+        return doc;
+    }
+
+    public static loadCurrentUser(): Promise<any> {
+        let userPromise = rp.get(ServerUtils.prepend(RouteStore.getCurrUser)).then((response) => {
+            if (response) {
+                let obj = JSON.parse(response);
                 CurrentUserUtils.curr_id = obj.id as string;
                 CurrentUserUtils.curr_email = obj.email as string;
             } else {
                 throw new Error("There should be a user! Why does Dash think there isn't one?")
             }
         });
+        let userDocPromise = rp.get(ServerUtils.prepend(RouteStore.getUserDocumentId)).then(id => {
+            if (id) {
+                return Server.GetField(id).then(field => {
+                    if (field instanceof Document) {
+                        this.user_document = field;
+                    } else {
+                        this.user_document = this.createUserDocument(id);
+                    }
+                })
+            } else {
+                throw new Error("There should be a user id! Why does Dash think there isn't one?")
+            }
+        });
+        return Promise.all([userPromise, userDocPromise]);
     }
 }
\ No newline at end of file
diff --git a/src/server/authentication/models/user_model.ts b/src/server/authentication/models/user_model.ts
index 3d4ed6896..81580aad5 100644
--- a/src/server/authentication/models/user_model.ts
+++ b/src/server/authentication/models/user_model.ts
@@ -21,9 +21,7 @@ export type DashUserModel = mongoose.Document & {
     passwordResetToken: string | undefined,
     passwordResetExpires: Date | undefined,
 
-    allWorkspaceIds: Array<String>,
-    activeWorkspaceId: String,
-    activeUsersId: String,
+    userDocumentId: string;
 
     profile: {
         name: string,
@@ -49,12 +47,7 @@ const userSchema = new mongoose.Schema({
     passwordResetToken: String,
     passwordResetExpires: Date,
 
-    allWorkspaceIds: {
-        type: Array,
-        default: []
-    },
-    activeWorkspaceId: String,
-    activeUsersId: String,
+    userDocumentId: String,
 
     facebook: String,
     twitter: String,
diff --git a/src/server/index.ts b/src/server/index.ts
index d1eb6847d..16304f1c5 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -156,16 +156,9 @@ addSecureRoute(
 
 addSecureRoute(
     Method.GET,
-    (user, res) => res.send(user.activeWorkspaceId || ""),
+    (user, res) => res.send(user.userDocumentId || ""),
     undefined,
-    RouteStore.getActiveWorkspace,
-);
-
-addSecureRoute(
-    Method.GET,
-    (user, res) => res.send(JSON.stringify(user.allWorkspaceIds)),
-    undefined,
-    RouteStore.getAllWorkspaces
+    RouteStore.getUserDocumentId,
 );
 
 addSecureRoute(
@@ -182,28 +175,6 @@ addSecureRoute(
 
 // SETTERS
 
-addSecureRoute(
-    Method.POST,
-    (user, res, req) => {
-        user.update({ $set: { activeWorkspaceId: req.body.target } }, (err, raw) => {
-            res.sendStatus(err ? 500 : 200);
-        });
-    },
-    undefined,
-    RouteStore.setActiveWorkspace
-);
-
-addSecureRoute(
-    Method.POST,
-    (user, res, req) => {
-        user.update({ $push: { allWorkspaceIds: req.body.target } }, (err, raw) => {
-            res.sendStatus(err ? 500 : 200);
-        });
-    },
-    undefined,
-    RouteStore.addWorkspace
-);
-
 addSecureRoute(
     Method.POST,
     (user, res, req) => {
-- 
cgit v1.2.3-70-g09d2

