From b78da60d91e37889c30b4428a88c838a9dafe5ca Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Wed, 17 Jul 2019 15:02:33 -0400
Subject: search auto focuses

---
 src/client/views/MainView.tsx | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

(limited to 'src/client/views/MainView.tsx')

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index ce7369220..5cb1d06cb 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -39,6 +39,8 @@ import { PreviewCursor } from './PreviewCursor';
 import { FilterBox } from './search/FilterBox';
 import { CollectionTreeView } from './collections/CollectionTreeView';
 import { ClientUtils } from '../util/ClientUtils';
+import { SearchBox } from './search/SearchBox';
+
 
 @observer
 export class MainView extends React.Component {
@@ -439,12 +441,11 @@ export class MainView extends React.Component {
     }
 
     @observable isSearchVisible = false;
-    @action
+    @action.bound
     toggleSearch = () => {
         this.isSearchVisible = !this.isSearchVisible;
     }
 
-
     render() {
         return (
             <div id="main-div">
-- 
cgit v1.2.3-70-g09d2


From 180a1268d6e732bca9557da7f935ec540de4b878 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Tue, 13 Aug 2019 16:31:34 -0400
Subject: key restrictions working properly

---
 src/client/views/MainView.tsx                      |  2 +-
 .../views/collections/CollectionViewChromes.tsx    | 73 +++++++++++++++++-----
 src/client/views/collections/KeyRestrictionRow.tsx |  6 +-
 3 files changed, 62 insertions(+), 19 deletions(-)

(limited to 'src/client/views/MainView.tsx')

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 031478477..daa047797 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -478,7 +478,7 @@ export class MainView extends React.Component {
         };
         return < div id="add-nodes-menu" style={{ left: this.flyoutWidth + 20, bottom: 20 }} >
             <input type="checkbox" id="add-menu-toggle" ref={this.addMenuToggle} />
-            <label htmlFor="add-menu-toggle" style={{ marginTop: 2 }} title="Add Node"><p>+</p></label>
+            <label htmlFor="add-menu-toggle" style={{ marginTop: 2 }} title="Close Menu"><p>+</p></label>
 
             <div id="add-options-content">
                 <ul id="add-options-list">
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index 9e4a4ac5a..9ac724ba8 100644
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ b/src/client/views/collections/CollectionViewChromes.tsx
@@ -23,6 +23,7 @@ import { Id } from "../../../new_fields/FieldSymbols";
 import { threadId } from "worker_threads";
 const datepicker = require('js-datepicker');
 import * as $ from 'jquery';
+import { firebasedynamiclinks } from "googleapis/build/src/apis/firebasedynamiclinks";
 
 interface CollectionViewChromeProps {
     CollectionView: CollectionView;
@@ -30,6 +31,12 @@ interface CollectionViewChromeProps {
     collapse?: (value: boolean) => any;
 }
 
+interface Filter {
+    key: string;
+    value: string;
+    contains: boolean;
+}
+
 let stopPropagation = (e: React.SyntheticEvent) => e.stopPropagation();
 
 @observer
@@ -42,12 +49,47 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
     @observable private _keyRestrictions: [JSX.Element, string][] = [];
     @observable private _collapsed: boolean = false;
     @computed private get filterValue() { return Cast(this.props.CollectionView.props.Document.viewSpecScript, ScriptField); }
-    // private _fullScript: string = "return true";
-    // @observable private keys: Object = new Object();
 
     private _picker: any;
     private _datePickerElGuid = Utils.GenerateGuid();
 
+    getFilters = (script: string) => {
+        let re: any = /(!)?\(\(\(doc\.(\w+)\s+&&\s+\(doc\.\w+\s+as\s+\w+\)\.includes\(\"(\w+)\"\)/g;
+        let arr: any[] = re.exec(script);
+        let toReturn: Filter[] = [];
+        if (arr !== null) {
+            let filter: Filter = {
+                key: arr[2],
+                value: arr[3],
+                contains: (arr[1] === "!") ? false : true,
+            };
+            toReturn.push(filter);
+            script = script.replace(arr[0], "");
+            if (re.exec(script) !== null) {
+                toReturn.push(...this.getFilters(script));
+            }
+            else { return toReturn; }
+        }
+        return toReturn;
+    }
+
+    addKeyRestrictions = (fields: Filter[]) => {
+
+        if (fields.length !== 0) {
+            for (let i = 0; i < fields.length; i++) {
+                this._keyRestrictions.push([<KeyRestrictionRow field={fields[i].key} value={fields[i].value} key={Utils.GenerateGuid()} contains={fields[i].contains} script={(value: string) => runInAction(() => this._keyRestrictions[i][1] = value)} />, ""]);
+
+            }
+            if (this._keyRestrictions.length === 1) {
+                this._keyRestrictions.push([<KeyRestrictionRow field="" value="" key={Utils.GenerateGuid()} contains={true} script={(value: string) => runInAction(() => this._keyRestrictions[1][1] = value)} />, ""]);
+            }
+        }
+        else {
+            this._keyRestrictions.push([<KeyRestrictionRow field="" value="" key={Utils.GenerateGuid()} contains={true} script={(value: string) => runInAction(() => this._keyRestrictions[0][1] = value)} />, ""]);
+            this._keyRestrictions.push([<KeyRestrictionRow field="" value="" key={Utils.GenerateGuid()} contains={false} script={(value: string) => runInAction(() => this._keyRestrictions[1][1] = value)} />, ""]);
+        }
+    }
+
     componentDidMount = () => {
         setTimeout(() => this._picker = datepicker("#" + this._datePickerElGuid, {
             disabler: (date: Date) => date > new Date(),
@@ -55,21 +97,14 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
             dateSelected: new Date()
         }), 1000);
 
-        // let reg: RegExp = new RegExp('(!)?\(\(\(doc\.(\w+)\s+&&\s+\(doc\.\w+\s+as\s+\w+\)\.includes\(\"(\w+)\"\)');
-        let re: any = /(!)?\(\(\(doc\.(\w+)\s+&&\s+\(doc\.\w+\s+as\s+\w+\)\.includes\(\"(\w+)\"\)/;
-        let arr: any[] = [];
+        let fields: Filter[] = [];
         if (this.filterValue) {
-            console.log("filter exists!")
-            arr = re.exec(this.filterValue.script.originalScript)
-            console.log(arr)
+            let string = this.filterValue.script.originalScript;
+            fields = this.getFilters(string);
         }
 
-        // let matches: RegExpExecArray = [];
-
         runInAction(() => {
-            this._keyRestrictions.push([<KeyRestrictionRow key={Utils.GenerateGuid()} contains={true} script={(value: string) => runInAction(() => this._keyRestrictions[0][1] = value)} />, ""]);
-            this._keyRestrictions.push([<KeyRestrictionRow key={Utils.GenerateGuid()} contains={false} script={(value: string) => runInAction(() => this._keyRestrictions[1][1] = value)} />, ""]);
-
+            this.addKeyRestrictions(fields);
             // chrome status is one of disabled, collapsed, or visible. this determines initial state from document
             let chromeStatus = this.props.CollectionView.props.Document.chromeStatus;
             if (chromeStatus) {
@@ -129,17 +164,19 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
     @action
     addKeyRestriction = (e: React.MouseEvent) => {
         let index = this._keyRestrictions.length;
-        this._keyRestrictions.push([<KeyRestrictionRow key={Utils.GenerateGuid()} contains={true} script={(value: string) => runInAction(() => this._keyRestrictions[index][1] = value)} />, ""]);
+        this._keyRestrictions.push([<KeyRestrictionRow field="" value="" key={Utils.GenerateGuid()} contains={true} script={(value: string) => runInAction(() => this._keyRestrictions[index][1] = value)} />, ""]);
 
         this.openViewSpecs(e);
     }
 
-    @action
+    @action.bound
     applyFilter = (e: React.MouseEvent) => {
 
         this.openViewSpecs(e);
 
-        let keyRestrictionScript = this._keyRestrictions.map(i => i[1]).filter(i => i.length > 0).join(" && ");
+        console.log(this._keyRestrictions)
+
+        let keyRestrictionScript = "(" + this._keyRestrictions.map(i => i[1]).filter(i => i.length > 0).join(" && ") + ")";
         let yearOffset = this._dateWithinValue[1] === 'y' ? 1 : 0;
         let monthOffset = this._dateWithinValue[1] === 'm' ? parseInt(this._dateWithinValue[0]) : 0;
         let weekOffset = this._dateWithinValue[1] === 'w' ? parseInt(this._dateWithinValue[0]) : 0;
@@ -234,11 +271,15 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
             })} />);
     }
 
+    @action.bound
     clearFilter = () => {
         let compiled = CompileScript("return true", { params: { doc: Doc.name }, typecheck: false });
         if (compiled.compiled) {
             this.props.CollectionView.props.Document.viewSpecScript = new ScriptField(compiled);
         }
+
+        this._keyRestrictions = [];
+        this.addKeyRestrictions([]);
     }
 
     render() {
diff --git a/src/client/views/collections/KeyRestrictionRow.tsx b/src/client/views/collections/KeyRestrictionRow.tsx
index 1b59547d8..e35b7d7d3 100644
--- a/src/client/views/collections/KeyRestrictionRow.tsx
+++ b/src/client/views/collections/KeyRestrictionRow.tsx
@@ -7,12 +7,14 @@ import { Doc } from "../../../new_fields/Doc";
 interface IKeyRestrictionProps {
     contains: boolean;
     script: (value: string) => void;
+    field: string;
+    value: string;
 }
 
 @observer
 export default class KeyRestrictionRow extends React.Component<IKeyRestrictionProps> {
-    @observable private _key = "";
-    @observable private _value = "";
+    @observable private _key = this.props.field;
+    @observable private _value = this.props.value;
     @observable private _contains = this.props.contains;
 
     render() {
-- 
cgit v1.2.3-70-g09d2


From 18bc52d98999c6e0d7814429d8bb7358473e9aff Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Tue, 13 Aug 2019 16:48:58 -0400
Subject: adding web thing

---
 package.json                  | 2 +-
 src/client/views/MainView.tsx | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

(limited to 'src/client/views/MainView.tsx')

diff --git a/package.json b/package.json
index d699d1e6f..a4343982e 100644
--- a/package.json
+++ b/package.json
@@ -148,7 +148,7 @@
         "js-datepicker": "^4.6.6",
         "jsonwebtoken": "^8.5.0",
         "jsx-to-string": "^1.4.0",
-        "lodash": "^4.17.11",
+        "lodash": "^4.17.15",
         "mobile-detect": "^1.4.3",
         "mobx": "^5.9.0",
         "mobx-react": "^5.3.5",
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index b34a901e1..ae5f0b12f 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -448,6 +448,7 @@ export class MainView extends React.Component {
         //let addTreeNode = action(() => Docs.TreeDocument([CurrentUserUtils.UserDocument], { width: 250, height: 400, title: "Library:" + CurrentUserUtils.email, dropAction: "alias" }));
         // let addTreeNode = action(() => Docs.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", dropAction: "copy"  }));
         let addColNode = action(() => Docs.Create.FreeformDocument([], { width: this.pwidth * .7, height: this.pheight, title: "a freeform collection" }));
+        let addWebNode = action(() => Docs.Create.WebDocument("https://javascript.info/regexp-groups", { width: this.pwidth * .7, height: this.pheight, title: "a freeform collection" }));
         let addDragboxNode = action(() => Docs.Create.DragboxDocument({ width: 40, height: 40, title: "drag collection" }));
         let addImageNode = action(() => Docs.Create.ImageDocument(imgurl, { width: 200, title: "an image of a cat" }));
         let addButtonDocument = action(() => Docs.Create.ButtonDocument({ width: 150, height: 50, title: "Button" }));
@@ -457,6 +458,7 @@ export class MainView extends React.Component {
 
         let btns: [React.RefObject<HTMLDivElement>, IconName, string, () => Doc][] = [
             [React.createRef<HTMLDivElement>(), "object-group", "Add Collection", addColNode],
+            [React.createRef<HTMLDivElement>(), "globe-asia", "Add Website", addWebNode],
             [React.createRef<HTMLDivElement>(), "bolt", "Add Button", addButtonDocument],
             // [React.createRef<HTMLDivElement>(), "clone", "Add Docking Frame", addDockingNode],
             [React.createRef<HTMLDivElement>(), "cloud-upload-alt", "Import Directory", addImportCollectionNode],
-- 
cgit v1.2.3-70-g09d2


From 31e9872ec5ec5b84c645adcf7acf06e20e2dc060 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Tue, 13 Aug 2019 17:47:01 -0400
Subject: yikes

---
 src/client/views/MainView.tsx | 42 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 41 insertions(+), 1 deletion(-)

(limited to 'src/client/views/MainView.tsx')

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index ae5f0b12f..51eb79edc 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -40,6 +40,7 @@ import { CollectionTreeView } from './collections/CollectionTreeView';
 import { ClientUtils } from '../util/ClientUtils';
 import { SchemaHeaderField, RandomPastel } from '../../new_fields/SchemaHeaderField';
 import { DictationManager } from '../util/DictationManager';
+import * as $ from 'jquery';
 
 @observer
 export class MainView extends React.Component {
@@ -436,6 +437,40 @@ export class MainView extends React.Component {
         }
     }
 
+    // @computed
+    // get webURL() {
+    //     let URL: string = "";
+
+    //     return URL;
+    // }
+    @observable private webpageURL: string = "";
+
+    @action
+    onURLChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+        this.webpageURL = e.target.value;
+    }
+
+    @observable webDoc: Doc | undefined = undefined;
+
+    @action
+    onURLSubmit = () => {
+        this.webDoc = Docs.Create.WebDocument(this.webpageURL, { width: this.pwidth * .7, height: this.pheight, title: this.webpageURL });
+    }
+
+    @action
+    makeWebDocument() {
+        let mod = document.getElementById("webpage-input");
+        if (mod) mod.style.display = "flex";
+        while (true) {
+            if (this.webDoc !== undefined) {
+                if (mod) mod.style.display = "none";
+                console.log(this.webpageURL)
+                console.log(this.webDoc)
+                return this.webDoc;
+            }
+        }
+    }
+
 
     @observable private _colorPickerDisplay = false;
     /* for the expandable add nodes menu. Not included with the miscbuttons because once it expands it expands the whole div with it, making canvas interactions limited. */
@@ -448,7 +483,7 @@ export class MainView extends React.Component {
         //let addTreeNode = action(() => Docs.TreeDocument([CurrentUserUtils.UserDocument], { width: 250, height: 400, title: "Library:" + CurrentUserUtils.email, dropAction: "alias" }));
         // let addTreeNode = action(() => Docs.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", dropAction: "copy"  }));
         let addColNode = action(() => Docs.Create.FreeformDocument([], { width: this.pwidth * .7, height: this.pheight, title: "a freeform collection" }));
-        let addWebNode = action(() => Docs.Create.WebDocument("https://javascript.info/regexp-groups", { width: this.pwidth * .7, height: this.pheight, title: "a freeform collection" }));
+        let addWebNode = action(() => this.makeWebDocument());
         let addDragboxNode = action(() => Docs.Create.DragboxDocument({ width: 40, height: 40, title: "drag collection" }));
         let addImageNode = action(() => Docs.Create.ImageDocument(imgurl, { width: 200, title: "an image of a cat" }));
         let addButtonDocument = action(() => Docs.Create.ButtonDocument({ width: 150, height: 50, title: "Button" }));
@@ -482,6 +517,11 @@ export class MainView extends React.Component {
             DocServer.setFieldWriteMode("viewType", mode2);
         };
         return < div id="add-nodes-menu" style={{ left: this.flyoutWidth + 20, bottom: 20 }} >
+            <div className="webpage-input" id="webpage-input" style={{ width: "400px", height: "150px", display: "none", }}>
+                <input className="url-input" placeholder="Enter webpage URL" onChange={(this.onURLChange)} />
+                <button onClick={this.onURLSubmit}>Submit URL</button>
+            </div>
+
             <input type="checkbox" id="add-menu-toggle" ref={this.addMenuToggle} />
             <label htmlFor="add-menu-toggle" style={{ marginTop: 2 }} title="Close Menu"><p>+</p></label>
 
-- 
cgit v1.2.3-70-g09d2


From 81100809b0f824cfc1481b19dbe38c31814539e1 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Wed, 14 Aug 2019 17:20:57 -0400
Subject: drag new webpage and easy URL change working

---
 src/client/views/Main.scss         |  11 +++
 src/client/views/MainView.tsx      |  42 +-----------
 src/client/views/nodes/WebBox.scss | 133 ++++++++++++++++++++++++++++++++++---
 src/client/views/nodes/WebBox.tsx  |  87 +++++++++++++++++++++++-
 4 files changed, 222 insertions(+), 51 deletions(-)

(limited to 'src/client/views/MainView.tsx')

diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss
index f76abaff3..d84decdfe 100644
--- a/src/client/views/Main.scss
+++ b/src/client/views/Main.scss
@@ -295,4 +295,15 @@ ul#add-options-list {
     z-index: 999;
     transition: 0.5s all ease;
     pointer-events: none;
+}
+
+.webpage-input {
+    display: none;
+    height: 60px;
+    width: 600px;
+    position: absolute;
+
+    .url-input {
+        width: 80%;
+    }
 }
\ No newline at end of file
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 51eb79edc..5b19e95ed 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -41,6 +41,7 @@ import { ClientUtils } from '../util/ClientUtils';
 import { SchemaHeaderField, RandomPastel } from '../../new_fields/SchemaHeaderField';
 import { DictationManager } from '../util/DictationManager';
 import * as $ from 'jquery';
+import { KeyValueBox } from './nodes/KeyValueBox';
 
 @observer
 export class MainView extends React.Component {
@@ -437,41 +438,6 @@ export class MainView extends React.Component {
         }
     }
 
-    // @computed
-    // get webURL() {
-    //     let URL: string = "";
-
-    //     return URL;
-    // }
-    @observable private webpageURL: string = "";
-
-    @action
-    onURLChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-        this.webpageURL = e.target.value;
-    }
-
-    @observable webDoc: Doc | undefined = undefined;
-
-    @action
-    onURLSubmit = () => {
-        this.webDoc = Docs.Create.WebDocument(this.webpageURL, { width: this.pwidth * .7, height: this.pheight, title: this.webpageURL });
-    }
-
-    @action
-    makeWebDocument() {
-        let mod = document.getElementById("webpage-input");
-        if (mod) mod.style.display = "flex";
-        while (true) {
-            if (this.webDoc !== undefined) {
-                if (mod) mod.style.display = "none";
-                console.log(this.webpageURL)
-                console.log(this.webDoc)
-                return this.webDoc;
-            }
-        }
-    }
-
-
     @observable private _colorPickerDisplay = false;
     /* for the expandable add nodes menu. Not included with the miscbuttons because once it expands it expands the whole div with it, making canvas interactions limited. */
     nodesMenu() {
@@ -483,7 +449,7 @@ export class MainView extends React.Component {
         //let addTreeNode = action(() => Docs.TreeDocument([CurrentUserUtils.UserDocument], { width: 250, height: 400, title: "Library:" + CurrentUserUtils.email, dropAction: "alias" }));
         // let addTreeNode = action(() => Docs.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", dropAction: "copy"  }));
         let addColNode = action(() => Docs.Create.FreeformDocument([], { width: this.pwidth * .7, height: this.pheight, title: "a freeform collection" }));
-        let addWebNode = action(() => this.makeWebDocument());
+        let addWebNode = action(() => Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" }));
         let addDragboxNode = action(() => Docs.Create.DragboxDocument({ width: 40, height: 40, title: "drag collection" }));
         let addImageNode = action(() => Docs.Create.ImageDocument(imgurl, { width: 200, title: "an image of a cat" }));
         let addButtonDocument = action(() => Docs.Create.ButtonDocument({ width: 150, height: 50, title: "Button" }));
@@ -517,10 +483,6 @@ export class MainView extends React.Component {
             DocServer.setFieldWriteMode("viewType", mode2);
         };
         return < div id="add-nodes-menu" style={{ left: this.flyoutWidth + 20, bottom: 20 }} >
-            <div className="webpage-input" id="webpage-input" style={{ width: "400px", height: "150px", display: "none", }}>
-                <input className="url-input" placeholder="Enter webpage URL" onChange={(this.onURLChange)} />
-                <button onClick={this.onURLSubmit}>Submit URL</button>
-            </div>
 
             <input type="checkbox" id="add-menu-toggle" ref={this.addMenuToggle} />
             <label htmlFor="add-menu-toggle" style={{ marginTop: 2 }} title="Close Menu"><p>+</p></label>
diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss
index eb09b0693..c37f08eca 100644
--- a/src/client/views/nodes/WebBox.scss
+++ b/src/client/views/nodes/WebBox.scss
@@ -1,16 +1,18 @@
-
-.webBox-cont, .webBox-cont-interactive{
+.webBox-cont,
+.webBox-cont-interactive {
     padding: 0vw;
     position: absolute;
     top: 0;
-    left:0;
+    left: 0;
     width: 100%;
     height: 100%;
     overflow: auto;
-    pointer-events: none ;
+    pointer-events: none;
 }
+
 .webBox-cont-interactive {
     pointer-events: all;
+
     span {
         user-select: text !important;
     }
@@ -18,8 +20,8 @@
 
 #webBox-htmlSpan {
     position: absolute;
-    top:0;
-    left:0;
+    top: 0;
+    left: 0;
 }
 
 .webBox-overlay {
@@ -29,8 +31,123 @@
 }
 
 .webBox-button {
-    padding : 0vw;
+    padding: 0vw;
     border: none;
-    width : 100%;
+    width: 100%;
+    height: 100%;
+}
+
+.webView-urlEditor {
+    position: relative;
+    opacity: 0.9;
+    z-index: 9001;
+    transition: top .5s;
+    background: lightgrey;
+    padding: 10px;
+
+
+    .urlEditor {
+        display: grid;
+        grid-template-columns: 1fr auto;
+        padding-bottom: 10px;
+        overflow: hidden;
+
+        .collectionViewBaseChrome {
+            display: flex;
+
+            .collectionViewBaseChrome-viewPicker {
+                font-size: 75%;
+                text-transform: uppercase;
+                letter-spacing: 2px;
+                background: rgb(238, 238, 238);
+                color: grey;
+                outline-color: black;
+                border: none;
+                padding: 12px 10px 11px 10px;
+                margin-left: 50px;
+            }
+
+            .collectionViewBaseChrome-viewPicker:active {
+                outline-color: black;
+            }
+
+            .collectionViewBaseChrome-collapse {
+                transition: all .5s, opacity 0.3s;
+                position: absolute;
+                width: 40px;
+                transform-origin: top left;
+                // margin-top: 10px;
+            }
+
+            .collectionViewBaseChrome-viewSpecs {
+                margin-left: 10px;
+                display: grid;
+
+
+
+                .collectionViewBaseChrome-viewSpecsMenu {
+                    overflow: hidden;
+                    transition: height .5s, display .5s;
+                    position: absolute;
+                    top: 60px;
+                    z-index: 100;
+                    display: flex;
+                    flex-direction: column;
+                    background: rgb(238, 238, 238);
+                    box-shadow: grey 2px 2px 4px;
+
+                    .qs-datepicker {
+                        left: unset;
+                        right: 0;
+                    }
+
+                    .collectionViewBaseChrome-viewSpecsMenu-row {
+                        display: grid;
+                        grid-template-columns: 150px 200px 150px;
+                        margin-top: 10px;
+                        margin-right: 10px;
+
+                        .collectionViewBaseChrome-viewSpecsMenu-rowLeft,
+                        .collectionViewBaseChrome-viewSpecsMenu-rowMiddle,
+                        .collectionViewBaseChrome-viewSpecsMenu-rowRight {
+                            font-size: 75%;
+                            letter-spacing: 2px;
+                            color: grey;
+                            margin-left: 10px;
+                            padding: 5px;
+                            border: none;
+                            outline-color: black;
+                        }
+                    }
+
+                    .collectionViewBaseChrome-viewSpecsMenu-lastRow {
+                        display: grid;
+                        grid-template-columns: 1fr 1fr 1fr;
+                        grid-gap: 10px;
+                        margin: 10px;
+                    }
+                }
+            }
+        }
+
+        button:hover {
+            transform: scale(1);
+        }
+
+        .collectionStackingViewChrome-sectionFilter:hover {
+            cursor: text;
+        }
+    }
+}
+
+.webpage-urlInput {
+    padding: 12px 10px 11px 10px;
+    border: 0px;
+    color: grey;
+    letter-spacing: 2px;
+    outline-color: black;
+    background: rgb(238, 238, 238);
+    width: 100%;
+    margin-right: 10px;
     height: 100%;
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index c8749b7cd..ff5297783 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -7,13 +7,23 @@ import { FieldView, FieldViewProps } from './FieldView';
 import "./WebBox.scss";
 import React = require("react");
 import { InkTool } from "../../../new_fields/InkField";
-import { Cast, FieldValue, NumCast } from "../../../new_fields/Types";
+import { Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types";
 import { Utils } from "../../../Utils";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { observable, action, computed } from "mobx";
+import { listSpec } from "../../../new_fields/Schema";
+import { Field, FieldResult } from "../../../new_fields/Doc";
+import { RefField } from "../../../new_fields/RefField";
+import { ObjectField } from "../../../new_fields/ObjectField";
+import { updateSourceFile } from "typescript";
+import { KeyValueBox } from "./KeyValueBox";
 
 @observer
 export class WebBox extends React.Component<FieldViewProps> {
 
     public static LayoutString() { return FieldView.LayoutString(WebBox); }
+    @observable private collapsed: boolean = true;
+    @observable private url: string = "";
 
     componentWillMount() {
 
@@ -30,6 +40,76 @@ export class WebBox extends React.Component<FieldViewProps> {
         }
     }
 
+    @action
+    onURLChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+        this.url = e.target.value;
+    }
+
+    @action
+    submitURL = () => {
+        const script = KeyValueBox.CompileKVPScript(`new WebField("${this.url}")`);
+        if (!script) return;
+        KeyValueBox.ApplyKVPScript(this.props.Document, "data", script);
+        let mod = document.getElementById("webpage-input");
+        if (mod) mod.style.display = "none";
+    }
+
+    @computed
+    get getURL() {
+        let urlField: FieldResult<WebField> = Cast(this.props.Document.data, WebField)
+        if (urlField) return urlField.url.toString();
+        return "";
+    }
+
+    onValueKeyDown = async (e: React.KeyboardEvent) => {
+        if (e.key === "Enter") {
+            e.stopPropagation();
+            this.submitURL();
+        }
+    }
+
+    urlEditor() {
+        return (
+            <div className="webView-urlEditor" style={{ top: this.collapsed ? -70 : 0 }}>
+                <div className="urlEditor">
+                    <div className="collectionViewBaseChrome">
+                        <button className="collectionViewBaseChrome-collapse"
+                            style={{
+                                top: this.collapsed ? 70 : 10,
+                                transform: `rotate(${this.collapsed ? 180 : 0}deg) scale(${this.collapsed ? 0.5 : 1}) translate(${this.collapsed ? "-100%, -100%" : "0, 0"})`,
+                                opacity: (this.collapsed && !this.props.isSelected()) ? 0 : 0.9,
+                                left: (this.collapsed ? 0 : "unset"),
+                            }}
+                            title="Collapse Url Editor" onClick={this.toggleCollapse}>
+                            <FontAwesomeIcon icon="caret-up" size="2x" />
+                        </button>
+                        <div style={{ marginLeft: 54, width: "100%", display: this.collapsed ? "none" : "flex" }}>
+                            <input className="webpage-urlInput"
+                                placeholder="ENTER URL"
+                                value={this.getURL}
+                                onChange={this.onURLChange}
+                                onKeyDown={this.onValueKeyDown}
+                            // onPointerDown={this.openViewSpecs}
+                            />
+                            <button className="submitUrl" onClick={this.submitURL}>
+                                SUBMIT URL
+                            </button>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        );
+    }
+
+    @action
+    toggleCollapse = () => {
+        // this.props.CollectionView.props.Document.chromeStatus = this.props.CollectionView.props.Document.chromeStatus === "enabled" ? "this.collapsed" : "enabled";
+        // if (this.props.collapse) {
+        //     this.props.collapse(this.props.CollectionView.props.Document.chromeStatus !== "enabled");
+        // }
+        this.collapsed = !this.collapsed;
+    }
+
     _ignore = 0;
     onPreWheel = (e: React.WheelEvent) => {
         this._ignore = e.timeStamp;
@@ -53,12 +133,13 @@ export class WebBox extends React.Component<FieldViewProps> {
         if (field instanceof HtmlField) {
             view = <span id="webBox-htmlSpan" dangerouslySetInnerHTML={{ __html: field.html }} />;
         } else if (field instanceof WebField) {
-            view = <iframe src={Utils.CorsProxy(field.url.href)} style={{ position: "absolute", width: "100%", height: "100%" }} />;
+            view = <iframe src={Utils.CorsProxy(field.url.href)} style={{ position: "absolute", width: "100%", height: "100%", top: 0 }} />;
         } else {
-            view = <iframe src={"https://crossorigin.me/https://cs.brown.edu"} style={{ position: "absolute", width: "100%", height: "100%" }} />;
+            view = <iframe src={"https://crossorigin.me/https://cs.brown.edu"} style={{ position: "absolute", width: "100%", height: "100%", top: 0 }} />;
         }
         let content =
             <div style={{ width: "100%", height: "100%", position: "absolute" }} onWheel={this.onPostWheel} onPointerDown={this.onPostPointer} onPointerMove={this.onPostPointer} onPointerUp={this.onPostPointer}>
+                {this.urlEditor()}
                 {view}
             </div>;
 
-- 
cgit v1.2.3-70-g09d2


From ca42398e6c636c0e0b4ad8165c63d6ec4934abfe Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 15 Aug 2019 23:43:16 -0400
Subject: tweaks

---
 src/client/views/MainView.tsx | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

(limited to 'src/client/views/MainView.tsx')

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 6e240817c..84fdf13a1 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -1,29 +1,33 @@
 import { IconName, library } from '@fortawesome/fontawesome-svg-core';
-import { faArrowDown, faCloudUploadAlt, faArrowUp, faClone, faCheck, faPlay, faPause, faCaretUp, faLongArrowAltRight, faCommentAlt, faCut, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faPortrait, faMusic, faObjectGroup, faPenNib, faRedoAlt, faTable, faThumbtack, faTree, faUndoAlt, faCat, faBolt } from '@fortawesome/free-solid-svg-icons';
+import { faArrowDown, faArrowUp, faBolt, faCaretUp, faCat, faCheck, faClone, faCloudUploadAlt, faCommentAlt, faCut, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faLongArrowAltRight, faMusic, faObjectGroup, faPause, faPenNib, faPlay, faPortrait, faRedoAlt, faTable, faThumbtack, faTree, faUndoAlt } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, configure, observable, runInAction, reaction, trace, autorun } from 'mobx';
+import { action, computed, configure, observable, reaction, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import "normalize.css";
 import * as React from 'react';
 import { SketchPicker } from 'react-color';
 import Measure from 'react-measure';
-import { Doc, DocListCast, Opt, HeightSym } from '../../new_fields/Doc';
+import { Doc, DocListCast, HeightSym, Opt } from '../../new_fields/Doc';
 import { Id } from '../../new_fields/FieldSymbols';
 import { InkTool } from '../../new_fields/InkField';
 import { List } from '../../new_fields/List';
 import { listSpec } from '../../new_fields/Schema';
-import { Cast, FieldValue, NumCast, BoolCast, StrCast } from '../../new_fields/Types';
+import { SchemaHeaderField } from '../../new_fields/SchemaHeaderField';
+import { BoolCast, Cast, FieldValue, StrCast } from '../../new_fields/Types';
 import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
 import { RouteStore } from '../../server/RouteStore';
-import { emptyFunction, returnOne, returnTrue, Utils, returnEmptyString } from '../../Utils';
+import { emptyFunction, returnEmptyString, returnOne, returnTrue, Utils } from '../../Utils';
 import { DocServer } from '../DocServer';
 import { Docs } from '../documents/Documents';
+import { ClientUtils } from '../util/ClientUtils';
+import { DictationManager } from '../util/DictationManager';
 import { SetupDrag } from '../util/DragManager';
 import { HistoryUtil } from '../util/History';
 import { Transform } from '../util/Transform';
 import { UndoManager } from '../util/UndoManager';
 import { CollectionBaseView } from './collections/CollectionBaseView';
 import { CollectionDockingView } from './collections/CollectionDockingView';
+import { CollectionTreeView } from './collections/CollectionTreeView';
 import { ContextMenu } from './ContextMenu';
 import { DocumentDecorations } from './DocumentDecorations';
 import KeyManager from './GlobalKeyHandler';
@@ -36,13 +40,6 @@ import PDFMenu from './pdf/PDFMenu';
 import { PresentationView } from './presentationview/PresentationView';
 import { PreviewCursor } from './PreviewCursor';
 import { FilterBox } from './search/FilterBox';
-import { CollectionTreeView } from './collections/CollectionTreeView';
-import { ClientUtils } from '../util/ClientUtils';
-import { SearchBox } from './search/SearchBox';
-import { SchemaHeaderField, RandomPastel } from '../../new_fields/SchemaHeaderField';
-import { DictationManager } from '../util/DictationManager';
-import * as $ from 'jquery';
-import { KeyValueBox } from './nodes/KeyValueBox';
 
 @observer
 export class MainView extends React.Component {
-- 
cgit v1.2.3-70-g09d2

