From e4b22138e39244728144fbdd4c06e439be1b519a Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Fri, 10 Apr 2020 13:24:07 -0400
Subject: more cleanup for layoutDoc/dataDoc/rootDoc updates. fix to doc
 filtering checkboxes getting filtered. fix to template captions.  fixes to
 generalize LabelDoc's buttonParms

---
 src/client/views/collections/CollectionView.tsx | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

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

diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 8192e6751..821840e0b 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -354,14 +354,15 @@ export class CollectionView extends Touchable<FieldViewProps> {
             let newFacet: Opt<Doc>;
             if (nonNumbers / allCollectionDocs.length < .1) {
                 newFacet = Docs.Create.SliderDocument({ title: facetHeader });
+                const newFacetField = Doc.LayoutFieldKey(newFacet);
                 const ranged = Doc.readDocRangeFilter(this.props.Document, facetHeader);
                 Doc.GetProto(newFacet).type = DocumentType.COL; // forces item to show an open/close button instead ofa checkbox
                 newFacet.treeViewExpandedView = "layout";
                 newFacet.treeViewOpen = true;
-                newFacet._sliderMin = ranged === undefined ? minVal : ranged[0];
-                newFacet._sliderMax = ranged === undefined ? maxVal : ranged[1];
-                newFacet._sliderMinThumb = minVal;
-                newFacet._sliderMaxThumb = maxVal;
+                newFacet[newFacetField + "-min"] = ranged === undefined ? minVal : ranged[0];
+                newFacet[newFacetField + "-max"] = ranged === undefined ? maxVal : ranged[1];
+                Doc.GetProto(newFacet)[newFacetField + "-minThumb"] = minVal;
+                Doc.GetProto(newFacet)[newFacetField + "-maxThumb"] = maxVal;
                 newFacet.target = this.props.Document;
                 const scriptText = `setDocFilterRange(this.target, "${facetHeader}", range)`;
                 newFacet.onThumbChanged = ScriptField.MakeScript(scriptText, { this: Doc.name, range: "number" });
@@ -370,14 +371,12 @@ export class CollectionView extends Touchable<FieldViewProps> {
             } else {
                 newFacet = Docs.Create.TreeDocument([], { title: facetHeader, treeViewOpen: true, isFacetFilter: true });
                 const capturedVariables = { layoutDoc: this.props.Document, dataDoc: this.dataDoc };
-                const params = { layoutDoc: Doc.name, dataDoc: Doc.name, };
-                newFacet.data = ComputedField.MakeFunction(`readFacetData(layoutDoc, dataDoc, "${this.props.fieldKey}", "${facetHeader}")`, params, capturedVariables);
+                newFacet.data = ComputedField.MakeFunction(`readFacetData(layoutDoc, dataDoc, "${this.props.fieldKey}", "${facetHeader}")`, {}, capturedVariables);
             }
             newFacet && Doc.AddDocToList(facetCollection, this.props.fieldKey + "-filter", newFacet);
         }
     }
 
-
     onPointerDown = (e: React.PointerEvent) => {
         setupMoveUpEvents(this, e, action((e: PointerEvent, down: number[], delta: number[]) => {
             this._facetWidth = Math.max(this.props.ScreenToLocalTransform().transformPoint(e.clientX, 0)[0], 0);
@@ -385,11 +384,11 @@ export class CollectionView extends Touchable<FieldViewProps> {
         }), returnFalse, action(() => this._facetWidth = this.facetWidth() < 15 ? Math.min(this.props.PanelWidth() - 25, 200) : 0));
     }
     filterBackground = () => "dimGray";
+    get ignoreFields() { return ["_docFilters", "_docRangeFilters"]; } // this makes the tree view collection ignore these filters (otherwise, the filters would filter themselves)
     @computed get scriptField() {
         const scriptText = "setDocFilter(containingTreeView, heading, this.title, checked)";
         return ScriptField.MakeScript(scriptText, { this: Doc.name, heading: "string", checked: "string", containingTreeView: Doc.name });
     }
-    @computed get treeIgnoreFields() { return ["_facetCollection", "_docFilters"]; }
     @computed get filterView() {
         const facetCollection = this.props.Document;
         const flyout = (
@@ -419,7 +418,7 @@ export class CollectionView extends Touchable<FieldViewProps> {
                         NativeWidth={returnZero}
                         treeViewHideHeaderFields={true}
                         onCheckedClick={this.scriptField!}
-                        ignoreFields={this.treeIgnoreFields}
+                        ignoreFields={this.ignoreFields}
                         annotationsKey={""}
                         dontRegisterView={true}
                         PanelWidth={this.facetWidth}
-- 
cgit v1.2.3-70-g09d2


From 348e794e7ff341a4358be6ed9515fc6ae723092e Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samwilkins333@gmail.com>
Date: Sun, 12 Apr 2020 21:36:26 -0700
Subject: rough pass at collection map view

---
 package-lock.json                                  | 68 +++++++++++++++-----
 package.json                                       |  6 +-
 src/client/Network.ts                              | 13 ++++
 src/client/cognitive_services/CognitiveServices.ts |  1 -
 src/client/documents/Documents.ts                  |  9 ++-
 src/client/views/Main.tsx                          |  1 -
 .../views/collections/CollectionMapView.scss       |  4 ++
 src/client/views/collections/CollectionMapView.tsx | 72 ++++++++++++++++++++++
 src/client/views/collections/CollectionView.tsx    | 10 ++-
 src/new_fields/Types.ts                            |  1 +
 webpack.config.js                                  | 55 ++++++++++-------
 11 files changed, 195 insertions(+), 45 deletions(-)
 create mode 100644 src/client/views/collections/CollectionMapView.scss
 create mode 100644 src/client/views/collections/CollectionMapView.tsx

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

diff --git a/package-lock.json b/package-lock.json
index 1949a8a5c..f40dc7b0f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -584,6 +584,20 @@
                 "@types/node": "*"
             }
         },
+        "@types/google-maps-react": {
+            "version": "2.0.4",
+            "resolved": "https://registry.npmjs.org/@types/google-maps-react/-/google-maps-react-2.0.4.tgz",
+            "integrity": "sha512-8EGr84L6ozODnfjWN9xVUFIxFedBbZinuDe5lBEJ757yh/lZqoKkqxrYLqvrLksDRVVwQYwWdFvfEASujmk36A==",
+            "requires": {
+                "@types/googlemaps": "*",
+                "@types/react": "*"
+            }
+        },
+        "@types/googlemaps": {
+            "version": "3.39.3",
+            "resolved": "https://registry.npmjs.org/@types/googlemaps/-/googlemaps-3.39.3.tgz",
+            "integrity": "sha512-L8O9HAVFZj0TuiS8h5ORthiMsrrhjxTC8XUusp5k47oXCst4VTm+qWKvrAvmYMybZVokbp4Udco1mNwJrTNZPQ=="
+        },
         "@types/isstream": {
             "version": "0.1.0",
             "resolved": "https://registry.npmjs.org/@types/isstream/-/isstream-0.1.0.tgz",
@@ -750,7 +764,7 @@
         },
         "@types/passport": {
             "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.0.tgz",
+            "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.2.tgz",
             "integrity": "sha512-Pf39AYKf8q+YoONym3150cEwfUD66dtwHJWvbeOzKxnA0GZZ/vAXhNWv9vMhKyRQBQZiQyWQnhYBEBlKW6G8wg==",
             "requires": {
                 "@types/express": "*"
@@ -5615,7 +5629,8 @@
                 },
                 "ansi-regex": {
                     "version": "2.1.1",
-                    "bundled": true
+                    "bundled": true,
+                    "optional": true
                 },
                 "aproba": {
                     "version": "1.2.0",
@@ -5633,11 +5648,13 @@
                 },
                 "balanced-match": {
                     "version": "1.0.0",
-                    "bundled": true
+                    "bundled": true,
+                    "optional": true
                 },
                 "brace-expansion": {
                     "version": "1.1.11",
                     "bundled": true,
+                    "optional": true,
                     "requires": {
                         "balanced-match": "^1.0.0",
                         "concat-map": "0.0.1"
@@ -5650,15 +5667,18 @@
                 },
                 "code-point-at": {
                     "version": "1.1.0",
-                    "bundled": true
+                    "bundled": true,
+                    "optional": true
                 },
                 "concat-map": {
                     "version": "0.0.1",
-                    "bundled": true
+                    "bundled": true,
+                    "optional": true
                 },
                 "console-control-strings": {
                     "version": "1.1.0",
-                    "bundled": true
+                    "bundled": true,
+                    "optional": true
                 },
                 "core-util-is": {
                     "version": "1.0.2",
@@ -5761,7 +5781,8 @@
                 },
                 "inherits": {
                     "version": "2.0.4",
-                    "bundled": true
+                    "bundled": true,
+                    "optional": true
                 },
                 "ini": {
                     "version": "1.3.5",
@@ -5771,6 +5792,7 @@
                 "is-fullwidth-code-point": {
                     "version": "1.0.0",
                     "bundled": true,
+                    "optional": true,
                     "requires": {
                         "number-is-nan": "^1.0.0"
                     }
@@ -5783,17 +5805,20 @@
                 "minimatch": {
                     "version": "3.0.4",
                     "bundled": true,
+                    "optional": true,
                     "requires": {
                         "brace-expansion": "^1.1.7"
                     }
                 },
                 "minimist": {
                     "version": "0.0.8",
-                    "bundled": true
+                    "bundled": true,
+                    "optional": true
                 },
                 "minipass": {
                     "version": "2.9.0",
                     "bundled": true,
+                    "optional": true,
                     "requires": {
                         "safe-buffer": "^5.1.2",
                         "yallist": "^3.0.0"
@@ -5810,6 +5835,7 @@
                 "mkdirp": {
                     "version": "0.5.1",
                     "bundled": true,
+                    "optional": true,
                     "requires": {
                         "minimist": "0.0.8"
                     }
@@ -5890,7 +5916,8 @@
                 },
                 "number-is-nan": {
                     "version": "1.0.1",
-                    "bundled": true
+                    "bundled": true,
+                    "optional": true
                 },
                 "object-assign": {
                     "version": "4.1.1",
@@ -5900,6 +5927,7 @@
                 "once": {
                     "version": "1.4.0",
                     "bundled": true,
+                    "optional": true,
                     "requires": {
                         "wrappy": "1"
                     }
@@ -5975,7 +6003,8 @@
                 },
                 "safe-buffer": {
                     "version": "5.1.2",
-                    "bundled": true
+                    "bundled": true,
+                    "optional": true
                 },
                 "safer-buffer": {
                     "version": "2.1.2",
@@ -6005,6 +6034,7 @@
                 "string-width": {
                     "version": "1.0.2",
                     "bundled": true,
+                    "optional": true,
                     "requires": {
                         "code-point-at": "^1.0.0",
                         "is-fullwidth-code-point": "^1.0.0",
@@ -6022,6 +6052,7 @@
                 "strip-ansi": {
                     "version": "3.0.1",
                     "bundled": true,
+                    "optional": true,
                     "requires": {
                         "ansi-regex": "^2.0.0"
                     }
@@ -6060,11 +6091,13 @@
                 },
                 "wrappy": {
                     "version": "1.0.2",
-                    "bundled": true
+                    "bundled": true,
+                    "optional": true
                 },
                 "yallist": {
                     "version": "3.1.1",
-                    "bundled": true
+                    "bundled": true,
+                    "optional": true
                 }
             }
         },
@@ -6344,6 +6377,11 @@
                 }
             }
         },
+        "google-maps-react": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/google-maps-react/-/google-maps-react-2.0.2.tgz",
+            "integrity": "sha512-6cYauGwt22haDUrWxKQ6yoNOqjiuxHo8YYcmb+aBvNICokdXmZOUB6Ah4vD5VexMVlrwP2PFqA/D8sHpEB52KA=="
+        },
         "google-p12-pem": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.1.tgz",
@@ -14376,7 +14414,7 @@
         },
         "readable-stream": {
             "version": "2.3.6",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+            "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
             "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
             "requires": {
                 "core-util-is": "~1.0.0",
@@ -15990,7 +16028,7 @@
         },
         "strip-ansi": {
             "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+            "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
             "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
             "requires": {
                 "ansi-regex": "^2.0.0"
@@ -18303,7 +18341,7 @@
         },
         "wrap-ansi": {
             "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+            "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
             "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
             "requires": {
                 "string-width": "^1.0.1",
diff --git a/package.json b/package.json
index 440646c48..c742857ad 100644
--- a/package.json
+++ b/package.json
@@ -11,7 +11,7 @@
     },
     "scripts": {
         "start-release": "cross-env RELEASE=true NODE_OPTIONS=--max_old_space_size=4096 ts-node-dev -- src/server/index.ts",
-        "start": "cross-env HANDWRITING='61088486d76c4b12ba578775a5f55422' NODE_OPTIONS=--max_old_space_size=4096 ts-node-dev -- src/server/index.ts",
+        "start": "cross-env NODE_OPTIONS=--max_old_space_size=4096 ts-node-dev -- src/server/index.ts",
         "debug": "cross-env NODE_OPTIONS=--max_old_space_size=8192 ts-node-dev --inspect -- src/server/index.ts",
         "build": "cross-env NODE_OPTIONS=--max_old_space_size=8192 webpack --env production",
         "test": "mocha -r ts-node/register test/**/*.ts",
@@ -83,6 +83,7 @@
         "@types/express-validator": "^3.0.0",
         "@types/formidable": "^1.0.31",
         "@types/gapi": "0.0.39",
+        "@types/google-maps-react": "^2.0.4",
         "@types/jquery": "^3.3.31",
         "@types/jquery-awesome-cursor": "^0.3.0",
         "@types/jsonwebtoken": "^8.3.7",
@@ -162,6 +163,7 @@
         "formidable": "^1.2.1",
         "golden-layout": "^1.5.9",
         "google-auth-library": "^4.2.4",
+        "google-maps-react": "^2.0.2",
         "googleapis": "^40.0.0",
         "googlephotos": "^0.2.5",
         "howler": "^2.1.3",
@@ -258,4 +260,4 @@
         "xoauth2": "^1.2.0",
         "youtube": "^0.1.0"
     }
-}
+}
\ No newline at end of file
diff --git a/src/client/Network.ts b/src/client/Network.ts
index 6982ecf19..bd0e6e61a 100644
--- a/src/client/Network.ts
+++ b/src/client/Network.ts
@@ -4,10 +4,23 @@ import { Upload } from "../server/SharedMediaTypes";
 
 export namespace Networking {
 
+    const EnvVarCache = new Map<string, string>();
+
     export async function FetchFromServer(relativeRoute: string) {
         return (await fetch(relativeRoute)).text();
     }
 
+    export async function FetchEnvironmentVariable(varNameLiteral: string) {
+        let resolved = EnvVarCache.get(varNameLiteral);
+        if (!resolved) {
+            resolved = await FetchFromServer(`/environment/${varNameLiteral}`);
+            if (resolved !== undefined) {
+                EnvVarCache.set(varNameLiteral, resolved);
+            }
+        }
+        return resolved;
+    }
+
     export async function PostToServer(relativeRoute: string, body?: any) {
         const options = {
             uri: Utils.prepend(relativeRoute),
diff --git a/src/client/cognitive_services/CognitiveServices.ts b/src/client/cognitive_services/CognitiveServices.ts
index 5d83de233..3133bf4b1 100644
--- a/src/client/cognitive_services/CognitiveServices.ts
+++ b/src/client/cognitive_services/CognitiveServices.ts
@@ -8,7 +8,6 @@ import { UndoManager } from "../util/UndoManager";
 import requestPromise = require("request-promise");
 import { List } from "../../new_fields/List";
 import { ClientRecommender } from "../ClientRecommender";
-import { ImageBox } from "../views/nodes/ImageBox";
 
 type APIManager<D> = { converter: BodyConverter<D>, requester: RequestExecutor };
 type RequestExecutor = (apiKey: string, body: string, service: Service) => Promise<string>;
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 703c049cd..43e379125 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -49,6 +49,8 @@ import { ContextMenuProps } from "../views/ContextMenuItem";
 import { ContextMenu } from "../views/ContextMenu";
 import { LinkBox } from "../views/nodes/LinkBox";
 import { ScreenshotBox } from "../views/nodes/ScreenshotBox";
+import CollectionMapView from "../views/collections/CollectionMapView";
+import LocationField, { LocationData } from "../../new_fields/LocationField";
 const requestImageSize = require('../util/request-image-size');
 const path = require('path');
 
@@ -277,8 +279,7 @@ export namespace Docs {
             }],
             [DocumentType.SCREENSHOT, {
                 layout: { view: ScreenshotBox, dataField: data },
-                options: {}
-            }]
+            }],
         ]);
 
         // All document prototypes are initialized with at least these values
@@ -624,6 +625,10 @@ export namespace Docs {
             return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", backgroundColor: "black", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Linear }, id);
         }
 
+        export function MapDocument(documents: Array<Doc>, options: DocumentOptions = {}) {
+            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), options);
+        }
+
         export function CarouselDocument(documents: Array<Doc>, options: DocumentOptions) {
             return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Carousel });
         }
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 6d705aa44..b21eb9c8f 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -5,7 +5,6 @@ import * as ReactDOM from 'react-dom';
 import * as React from 'react';
 import { DocServer } from "../DocServer";
 import { AssignAllExtensions } from "../../extensions/General/Extensions";
-process.env.HANDWRITING = "61088486d76c4b12ba578775a5f55422";
 
 AssignAllExtensions();
 
diff --git a/src/client/views/collections/CollectionMapView.scss b/src/client/views/collections/CollectionMapView.scss
new file mode 100644
index 000000000..c74433902
--- /dev/null
+++ b/src/client/views/collections/CollectionMapView.scss
@@ -0,0 +1,4 @@
+.collectionMapView-contents {
+    width: 100%;
+    height: 100%;
+}
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionMapView.tsx b/src/client/views/collections/CollectionMapView.tsx
new file mode 100644
index 000000000..49411f61b
--- /dev/null
+++ b/src/client/views/collections/CollectionMapView.tsx
@@ -0,0 +1,72 @@
+import { observer } from "mobx-react";
+import { makeInterface } from "../../../new_fields/Schema";
+import { documentSchema } from "../../../new_fields/documentSchemas";
+import React = require("react");
+import { Map, Marker, MapProps, GoogleApiWrapper } from "google-maps-react";
+import { NumCast, StrCast } from "../../../new_fields/Types";
+import { CollectionSubView } from "./CollectionSubView";
+import { Utils } from "../../../Utils";
+
+type MapDocument = makeInterface<[typeof documentSchema]>;
+const MapDocument = makeInterface(documentSchema);
+
+export type LocationData = google.maps.LatLngLiteral & { address?: string };
+
+@observer
+class CollectionMapView extends CollectionSubView<MapDocument, Partial<MapProps> & { google: any }>(MapDocument) {
+
+    render() {
+        const { childLayoutPairs, props } = this;
+        const { Document } = props;
+        const center: LocationData = { lat: NumCast(Document.mapCenterLat), lng: NumCast(Document.mapCenterLng) };
+        if (!center.lat) {
+            center.lat = childLayoutPairs.length ? NumCast(childLayoutPairs[0].layout.locationLat, 0) : 0;
+            center.lng = childLayoutPairs.length ? NumCast(childLayoutPairs[0].layout.locationLng, 0) : 0;
+        }
+        return (
+            <div
+                className={"collectionMapView-contents"}
+            >
+                <Map
+                    {...props}
+                    zoom={NumCast(Document.zoom, 10)}
+                    center={center}
+                    initialCenter={center}
+                >
+                    {childLayoutPairs.map(({ layout }) => {
+                        const location: LocationData = {
+                            lat: NumCast(childLayoutPairs[0].layout.locationLat, 0),
+                            lng: NumCast(childLayoutPairs[0].layout.locationLng, 0)
+                        };
+                        const iconSize = new google.maps.Size(NumCast(layout.mapIconWidth, 45), NumCast(layout.mapIconHeight, 45));
+                        return (
+                            <Marker
+                                key={Utils.GenerateGuid()}
+                                label={StrCast(layout.title)}
+                                position={location}
+                                onClick={() => {
+                                    Document.mapCenterLat = location.lat;
+                                    Document.mapCenterLng = location.lng;
+                                }}
+                                icon={{
+                                    size: iconSize,
+                                    scaledSize: iconSize,
+                                    url: StrCast(Document.mapIconUrl, "https://www.pinclipart.com/picdir/middle/359-3598915_map-marker-icon-location-icon-png-clipart.png")
+                                }}
+                            />
+                        );
+                    })}
+                </Map>
+            </div>
+        );
+    }
+
+}
+
+declare var process: {
+    env: {
+        GOOGLE_MAPS_API_KEY: string;
+    }
+};
+
+export default GoogleApiWrapper({ apiKey: process.env.GOOGLE_MAPS_API_KEY })(CollectionMapView) as any;
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 821840e0b..d1dc32829 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -1,7 +1,7 @@
 import { library } from '@fortawesome/fontawesome-svg-core';
 import { faEye, faEdit } from '@fortawesome/free-regular-svg-icons';
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { faColumns, faCopy, faEllipsisV, faFingerprint, faImage, faProjectDiagram, faSignature, faSquare, faTh, faThList, faTree } from '@fortawesome/free-solid-svg-icons';
+import { faColumns, faCopy, faEllipsisV, faFingerprint, faImage, faProjectDiagram, faSignature, faSquare, faTh, faThList, faTree, faGlobeAmericas } from '@fortawesome/free-solid-svg-icons';
 import { action, observable, computed } from 'mobx';
 import { observer } from "mobx-react";
 import * as React from 'react';
@@ -44,12 +44,15 @@ import { Docs } from '../../documents/Documents';
 import { ScriptField, ComputedField } from '../../../new_fields/ScriptField';
 import { InteractionUtils } from '../../util/InteractionUtils';
 import { ObjectField } from '../../../new_fields/ObjectField';
+import CollectionMapView from './CollectionMapView';
+import { ClientUtils } from '../../util/ClientUtils';
+import { GoogleApiWrapper } from 'google-maps-react';
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
 export const COLLECTION_BORDER_WIDTH = 2;
 const path = require('path');
-library.add(faTh, faTree, faSquare, faProjectDiagram, faSignature, faThList, faFingerprint, faColumns, faEllipsisV, faImage, faEye as any, faCopy);
+library.add(faTh, faTree, faSquare, faProjectDiagram, faSignature, faThList, faFingerprint, faColumns, faGlobeAmericas, faEllipsisV, faImage, faEye as any, faCopy);
 
 export enum CollectionViewType {
     Invalid = "invalid",
@@ -65,6 +68,7 @@ export enum CollectionViewType {
     Carousel = "carousel",
     Linear = "linear",
     Staff = "staff",
+    Map = "map"
 }
 
 export interface CollectionRenderProps {
@@ -170,6 +174,7 @@ export class CollectionView extends Touchable<FieldViewProps> {
             case CollectionViewType.Stacking: { this.props.Document.singleColumn = true; return (<CollectionStackingView key="collview" {...props} />); }
             case CollectionViewType.Masonry: { this.props.Document.singleColumn = false; return (<CollectionStackingView key="collview" {...props} />); }
             case CollectionViewType.Time: { return (<CollectionTimeView key="collview" {...props} />); }
+            case CollectionViewType.Map: return (<CollectionMapView key="collview" {...props} />);
             case CollectionViewType.Freeform:
             default: { this.props.Document._freeformLayoutEngine = undefined; return (<CollectionFreeFormView key="collview" {...props} />); }
         }
@@ -211,6 +216,7 @@ export class CollectionView extends Touchable<FieldViewProps> {
             subItems.push({ description: "Masonry", event: () => this.props.Document._viewType = CollectionViewType.Masonry, icon: "columns" });
             subItems.push({ description: "Carousel", event: () => this.props.Document._viewType = CollectionViewType.Carousel, icon: "columns" });
             subItems.push({ description: "Pivot/Time", event: () => this.props.Document._viewType = CollectionViewType.Time, icon: "columns" });
+            subItems.push({ description: "Map", event: () => this.props.Document._viewType = CollectionViewType.Map, icon: "globe-americas" });
             switch (this.props.Document._viewType) {
                 case CollectionViewType.Freeform: {
                     subItems.push({ description: "Custom", icon: "fingerprint", event: AddCustomFreeFormLayout(this.props.Document, this.props.fieldKey) });
diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts
index 0ca35fab2..aa44cefa0 100644
--- a/src/new_fields/Types.ts
+++ b/src/new_fields/Types.ts
@@ -87,6 +87,7 @@ export function BoolCast(field: FieldResult, defaultVal: boolean | null = false)
 export function DateCast(field: FieldResult) {
     return Cast(field, DateField, null);
 }
+
 export function ScriptCast(field: FieldResult) {
     return Cast(field, ScriptField, null);
 }
diff --git a/webpack.config.js b/webpack.config.js
index 6a14dfcda..655334ef2 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -2,6 +2,14 @@ var path = require('path');
 var webpack = require('webpack');
 const CopyWebpackPlugin = require("copy-webpack-plugin");
 const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
+const env = require('dotenv').config().parsed;
+const envKeys = Object.keys(env).reduce((prev, next) => {
+    if (next.startsWith("DASH_")) {
+        const resolved = next.replace("DASH_", "");
+        prev[`process.env.${resolved}`] = JSON.stringify(env[next]);
+    }
+    return prev;
+}, {});
 
 module.exports = {
     mode: 'development',
@@ -33,17 +41,18 @@ module.exports = {
         extensions: ['.js', '.ts', '.tsx']
     },
     module: {
-        rules: [
-            {
+        rules: [{
                 test: [/\.tsx?$/],
-                use: [
-                    { loader: 'ts-loader', options: { transpileOnly: true } }
-                ]
+                use: [{
+                    loader: 'ts-loader',
+                    options: {
+                        transpileOnly: true
+                    }
+                }]
             },
             {
                 test: /\.scss|css$/,
-                use: [
-                    {
+                use: [{
                         loader: "style-loader"
                     },
                     {
@@ -56,28 +65,30 @@ module.exports = {
             },
             {
                 test: /\.(jpg|png|pdf)$/,
-                use: [
-                    {
-                        loader: 'file-loader'
-                    }
-                ]
+                use: [{
+                    loader: 'file-loader'
+                }]
             },
             {
                 test: /\.(png|jpg|gif)$/i,
-                use: [
-                    {
-                        loader: 'url-loader',
-                        options: {
-                            limit: 8192
-                        }
+                use: [{
+                    loader: 'url-loader',
+                    options: {
+                        limit: 8192
                     }
-                ]
-            }]
+                }]
+            }
+        ]
     },
     plugins: [
-        new CopyWebpackPlugin([{ from: "deploy", to: path.join(__dirname, "build") }]),
+        new CopyWebpackPlugin([{
+            from: "deploy",
+            to: path.join(__dirname, "build")
+        }]),
+        new webpack.DefinePlugin(envKeys),
         new ForkTsCheckerWebpackPlugin({
-            tslint: true, useTypescriptIncrementalApi: true
+            tslint: true,
+            useTypescriptIncrementalApi: true
         }),
         new webpack.optimize.OccurrenceOrderPlugin(),
         new webpack.HotModuleReplacementPlugin(),
-- 
cgit v1.2.3-70-g09d2


From b235c94614141752c98d24a395682a02297d9e6a Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Mon, 13 Apr 2020 11:15:59 -0400
Subject: cleaned up rootSelected() to work with templates.  adjusted nudge to
 favor moving documents over panning collection

---
 src/client/views/DocComponent.tsx                       |  4 ++--
 src/client/views/PreviewCursor.tsx                      | 14 +++++---------
 src/client/views/collections/CollectionSubView.tsx      |  2 +-
 src/client/views/collections/CollectionView.tsx         |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx       | 17 +++++++++++------
 .../collections/collectionFreeForm/MarqueeView.tsx      |  2 +-
 .../views/nodes/CollectionFreeFormDocumentView.tsx      |  4 ++--
 src/client/views/nodes/DocumentView.tsx                 | 16 +++++++++-------
 8 files changed, 32 insertions(+), 29 deletions(-)

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

diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index b1bd4191c..f19f9308a 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -53,7 +53,7 @@ export function ViewBoxBaseComponent<P extends ViewBoxBaseProps, T>(schemaCtor:
         // key where data is stored
         @computed get fieldKey() { return this.props.fieldKey; }
 
-        active = (outsideReaction?: boolean) => !this.props.Document.isBackground && ((this.props.Document.forceActive && this.props.rootSelected(outsideReaction)) || this.props.isSelected(outsideReaction) || this.props.renderDepth === 0);//  && !InkingControl.Instance.selectedTool;  // bcz: inking state shouldn't affect static tools 
+        active = (outsideReaction?: boolean) => !this.props.Document.isBackground && (this.props.rootSelected(outsideReaction) || this.props.isSelected(outsideReaction) || this.props.renderDepth === 0);//  && !InkingControl.Instance.selectedTool;  // bcz: inking state shouldn't affect static tools 
         protected multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer;
     }
     return Component;
@@ -114,7 +114,7 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T
 
         whenActiveChanged = action((isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive));
         active = (outsideReaction?: boolean) => ((InkingControl.Instance.selectedTool === InkTool.None && !this.props.Document.isBackground) &&
-            ((this.props.Document.forceActive && this.props.rootSelected(outsideReaction)) || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false)
+            (this.props.rootSelected(outsideReaction) || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false)
         annotationsActive = (outsideReaction?: boolean) => (InkingControl.Instance.selectedTool !== InkTool.None || (this.props.Document.isBackground && this.props.active()) ||
             (this.props.Document.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false)
     }
diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx
index ecebadd2a..92ba13d2f 100644
--- a/src/client/views/PreviewCursor.tsx
+++ b/src/client/views/PreviewCursor.tsx
@@ -13,7 +13,7 @@ export class PreviewCursor extends React.Component<{}> {
     static _getTransform: () => Transform;
     static _addLiveTextDoc: (doc: Doc) => void;
     static _addDocument: (doc: Doc) => boolean;
-    static _nudge: (x: number, y: number) => void;
+    static _nudge: (x: number, y: number) => boolean;
     @observable static _clickPoint = [0, 0];
     @observable public static Visible = false;
     constructor(props: any) {
@@ -91,17 +91,13 @@ export class PreviewCursor extends React.Component<{}> {
             }
         } else if (PreviewCursor.Visible) {
             if (e.key === "ArrowRight") {
-                PreviewCursor._nudge?.(1 * (e.shiftKey ? 2 : 1), 0);
-                e.stopPropagation();
+                PreviewCursor._nudge?.(1 * (e.shiftKey ? 2 : 1), 0) && e.stopPropagation();
             } else if (e.key === "ArrowLeft") {
-                PreviewCursor._nudge?.(-1 * (e.shiftKey ? 2 : 1), 0);
-                e.stopPropagation();
+                PreviewCursor._nudge?.(-1 * (e.shiftKey ? 2 : 1), 0) && e.stopPropagation();
             } else if (e.key === "ArrowUp") {
-                PreviewCursor._nudge?.(0, 1 * (e.shiftKey ? 2 : 1));
-                e.stopPropagation();
+                PreviewCursor._nudge?.(0, 1 * (e.shiftKey ? 2 : 1)) && e.stopPropagation();
             } else if (e.key === "ArrowDown") {
-                PreviewCursor._nudge?.(0, -1 * (e.shiftKey ? 2 : 1));
-                e.stopPropagation();
+                PreviewCursor._nudge?.(0, -1 * (e.shiftKey ? 2 : 1)) && e.stopPropagation();
             }
         }
     }
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 6b7c3de56..37cf942c6 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -100,7 +100,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
         }
 
         rootSelected = (outsideReaction?: boolean) => {
-            return this.props.isSelected(outsideReaction) || (this.props.Document.rootDocument || this.props.Document.forceActive ? this.props.rootSelected(outsideReaction) : false);
+            return this.props.isSelected(outsideReaction) || (this.rootDoc && this.props.rootSelected(outsideReaction));
         }
 
         // The data field for rendering this collection will be on the this.props.Document unless we're rendering a template in which case we try to use props.DataDoc.
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 821840e0b..86df9c080 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -102,7 +102,7 @@ export class CollectionView extends Touchable<FieldViewProps> {
         return viewField as any as CollectionViewType;
     }
 
-    active = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || (this.props.rootSelected(outsideReaction) && BoolCast(this.props.Document.forceActive)) || this._isChildActive || this.props.renderDepth === 0;
+    active = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || this.props.rootSelected(outsideReaction) || this.props.Document.forceActive || this._isChildActive || this.props.renderDepth === 0;
 
     whenActiveChanged = (isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive);
 
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 7dca19073..a77f09163 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -15,7 +15,7 @@ import { ScriptField } from "../../../../new_fields/ScriptField";
 import { BoolCast, Cast, FieldValue, NumCast, ScriptCast, StrCast } from "../../../../new_fields/Types";
 import { TraceMobx } from "../../../../new_fields/util";
 import { GestureUtils } from "../../../../pen-gestures/GestureUtils";
-import { aggregateBounds, intersectRect, returnOne, Utils, returnZero } from "../../../../Utils";
+import { aggregateBounds, intersectRect, returnOne, Utils, returnZero, returnFalse } from "../../../../Utils";
 import { CognitiveServices } from "../../../cognitive_services/CognitiveServices";
 import { DocServer } from "../../../DocServer";
 import { Docs } from "../../../documents/Documents";
@@ -43,6 +43,7 @@ import "./CollectionFreeFormView.scss";
 import MarqueeOptionsMenu from "./MarqueeOptionsMenu";
 import { MarqueeView } from "./MarqueeView";
 import React = require("react");
+import { CollectionViewType } from "../CollectionView";
 
 library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard, faFileUpload);
 
@@ -860,7 +861,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument, u
             LibraryPath: this.libraryPath,
             FreezeDimensions: this.props.freezeChildDimensions,
             layoutKey: undefined,
-            rootSelected: this.rootSelected,
+            rootSelected: childData ? this.rootSelected : returnFalse,
             dropAction: StrCast(this.props.Document.childDropAction) as dropActionType,
             //onClick: undefined, // this.props.onClick,  // bcz: check this out -- I don't think we want to inherit click handlers, or we at least need a way to ignore them
             onClick: this.onChildClickHandler,
@@ -1105,10 +1106,14 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument, u
 
     _nudgeTime = 0;
     nudge = action((x: number, y: number) => {
-        this.setPan(NumCast(this.layoutDoc._panX) + this.props.PanelWidth() / 2 * x / this.zoomScaling(),
-            NumCast(this.layoutDoc._panY) + this.props.PanelHeight() / 2 * (-y) / this.zoomScaling(), "Ease", true);
-        this._nudgeTime = Date.now();
-        setTimeout(() => (Date.now() - this._nudgeTime >= 500) && (this.Document.panTransformType = undefined), 500);
+        if (this.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Freeform) { // bcz: this isn't ideal, but want to try it out...
+            this.setPan(NumCast(this.layoutDoc._panX) + this.props.PanelWidth() / 2 * x / this.zoomScaling(),
+                NumCast(this.layoutDoc._panY) + this.props.PanelHeight() / 2 * (-y) / this.zoomScaling(), "Ease", true);
+            this._nudgeTime = Date.now();
+            setTimeout(() => (Date.now() - this._nudgeTime >= 500) && (this.Document.panTransformType = undefined), 500);
+            return true;
+        }
+        return false;
     });
     @computed get marqueeView() {
         return <MarqueeView {...this.props} nudge={this.nudge} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments} addDocument={this.addDocument}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 5a6c8573b..9dd3d640b 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -31,7 +31,7 @@ interface MarqueeViewProps {
     addLiveTextDocument: (doc: Doc) => void;
     isSelected: () => boolean;
     isAnnotationOverlay?: boolean;
-    nudge:(x:number, y:number) => void;
+    nudge: (x: number, y: number) => boolean;
     setPreviewCursor?: (func: (x: number, y: number, drag: boolean) => void) => void;
 }
 
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 3503af442..e7cb2c015 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -60,8 +60,8 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
         return undefined;
     }
     nudge = (x: number, y: number) => {
-        this.layoutDoc.x = NumCast(this.layoutDoc.x) + x;
-        this.layoutDoc.y = NumCast(this.layoutDoc.y) + y;
+        this.props.Document.x = NumCast(this.props.Document.x) + x;
+        this.props.Document.y = NumCast(this.props.Document.y) + y;
     }
 
     contentScaling = () => this.nativeWidth > 0 && !this.props.fitToBox && !this.freezeDimensions ? this.width / this.nativeWidth : 1;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 3784c5c9c..cc3c39154 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -289,13 +289,15 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             let preventDefault = true;
             this.props.Document.isBackground === undefined && this.props.bringToFront(this.props.Document);
             if (this._doubleTap && this.props.renderDepth && !this.onClickHandler?.script) { // disable double-click to show full screen for things that have an on click behavior since clicking them twice can be misinterpreted as a double click
-                const fullScreenAlias = Doc.MakeAlias(this.props.Document);
-                if (StrCast(fullScreenAlias.layoutKey) !== "layout_fullScreen" && fullScreenAlias.layout_fullScreen) {
-                    fullScreenAlias.layoutKey = "layout_fullScreen";
+                if (!(e.nativeEvent as any).formattedHandled) {
+                    const fullScreenAlias = Doc.MakeAlias(this.props.Document);
+                    if (StrCast(fullScreenAlias.layoutKey) !== "layout_fullScreen" && fullScreenAlias.layout_fullScreen) {
+                        fullScreenAlias.layoutKey = "layout_fullScreen";
+                    }
+                    UndoManager.RunInBatch(() => this.props.addDocTab(fullScreenAlias, "inTab"), "double tap");
+                    SelectionManager.DeselectAll();
+                    Doc.UnBrushDoc(this.props.Document);
                 }
-                UndoManager.RunInBatch(() => this.props.addDocTab(fullScreenAlias, "inTab"), "double tap");
-                SelectionManager.DeselectAll();
-                Doc.UnBrushDoc(this.props.Document);
             } else if (this.onClickHandler?.script) {
                 SelectionManager.DeselectAll();
                 const func = () => this.onClickHandler.script.run({
@@ -978,7 +980,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         return typeof fallback === "string" ? fallback : "layout";
     }
     rootSelected = (outsideReaction?: boolean) => {
-        return this.isSelected(outsideReaction) || (this.props.Document.forceActive && this.props.rootSelected?.(outsideReaction) ? true : false);
+        return this.isSelected(outsideReaction) || (this.rootDoc && this.props.rootSelected?.(outsideReaction));
     }
     childScaling = () => (this.layoutDoc._fitWidth ? this.props.PanelWidth() / this.nativeWidth : this.props.ContentScaling());
     panelWidth = () => this.props.PanelWidth();
-- 
cgit v1.2.3-70-g09d2


From 87268612b9b765d74f1a5317b0894be0ceb1dfd1 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Mon, 13 Apr 2020 16:43:50 -0400
Subject: fixed map view pointer events.

---
 src/client/views/collections/CollectionMapView.scss | 3 +++
 src/client/views/collections/CollectionMapView.tsx  | 8 ++++----
 src/client/views/collections/CollectionView.tsx     | 2 +-
 3 files changed, 8 insertions(+), 5 deletions(-)

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

diff --git a/src/client/views/collections/CollectionMapView.scss b/src/client/views/collections/CollectionMapView.scss
index c74433902..df7853da6 100644
--- a/src/client/views/collections/CollectionMapView.scss
+++ b/src/client/views/collections/CollectionMapView.scss
@@ -1,4 +1,7 @@
 .collectionMapView-contents {
     width: 100%;
     height: 100%;
+}
+.collectionMapView-contents-none {
+    pointer-events: none;
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionMapView.tsx b/src/client/views/collections/CollectionMapView.tsx
index b67daeb53..5075bbf7a 100644
--- a/src/client/views/collections/CollectionMapView.tsx
+++ b/src/client/views/collections/CollectionMapView.tsx
@@ -7,6 +7,7 @@ import { NumCast, StrCast } from "../../../new_fields/Types";
 import { CollectionSubView } from "./CollectionSubView";
 import { Utils } from "../../../Utils";
 import { Opt } from "../../../new_fields/Doc";
+import "./CollectionMapView.scss";
 
 type MapDocument = makeInterface<[typeof documentSchema]>;
 const MapDocument = makeInterface(documentSchema);
@@ -25,11 +26,10 @@ class CollectionMapView extends CollectionSubView<MapDocument, Partial<MapProps>
             center.lng = childLayoutPairs.length ? NumCast(childLayoutPairs[0].layout.locationLng, 0) : 0;
         }
         return (
-            <div
-                className={"collectionMapView-contents"}
-            >
+            <div className={"collectionMapView-contents" + (this.props.active() ? "" : "-none")}
+                onPointerDown={e => (this.props.active() && e.button === 0 && !e.ctrlKey) && e.stopPropagation()} >
                 <Map
-                    {...props}
+                    google={this.props.google}
                     zoom={NumCast(Document.zoom, 10)}
                     center={center}
                     initialCenter={center}
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 4d04f2050..8cc5146d5 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -106,7 +106,7 @@ export class CollectionView extends Touchable<FieldViewProps> {
         return viewField as any as CollectionViewType;
     }
 
-    active = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || this.props.rootSelected(outsideReaction) || this.props.Document.forceActive || this._isChildActive || this.props.renderDepth === 0;
+    active = (outsideReaction?: boolean) => (this.props.isSelected(outsideReaction) || this.props.rootSelected(outsideReaction) || this.props.Document.forceActive || this._isChildActive || this.props.renderDepth === 0) ? true : false;
 
     whenActiveChanged = (isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive);
 
-- 
cgit v1.2.3-70-g09d2


From 130e26103461f23a2d8b57ea2eef6b17eefb8f8e Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Mon, 13 Apr 2020 21:46:20 -0400
Subject: updated childDetailedView stuff for pivot view

---
 src/client/views/TemplateMenu.tsx                      |  4 ++--
 src/client/views/collections/CollectionTimeView.tsx    | 10 ++++++----
 src/client/views/collections/CollectionTreeView.tsx    |  2 +-
 src/client/views/collections/CollectionView.tsx        |  4 ++--
 src/client/views/collections/CollectionViewChromes.tsx |  4 ++--
 src/client/views/nodes/DocumentView.tsx                |  8 ++++----
 src/new_fields/Doc.ts                                  |  8 --------
 src/new_fields/documentSchemas.ts                      |  2 +-
 8 files changed, 18 insertions(+), 24 deletions(-)

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

diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index 4d7f1e443..b76137f06 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -167,8 +167,8 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
     }
 }
 
-Scripting.addGlobal(function switchView(doc: Doc, template: Doc) {
-    if (template.dragFactory) {
+Scripting.addGlobal(function switchView(doc: Doc, template: Doc | undefined) {
+    if (template?.dragFactory) {
         template = Cast(template.dragFactory, Doc, null);
     }
     const templateTitle = StrCast(template?.title);
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index 53de2fbbe..31b720b81 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -5,7 +5,7 @@ import { List } from "../../../new_fields/List";
 import { ObjectField } from "../../../new_fields/ObjectField";
 import { RichTextField } from "../../../new_fields/RichTextField";
 import { ComputedField, ScriptField } from "../../../new_fields/ScriptField";
-import { NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
+import { NumCast, StrCast, BoolCast, Cast } from "../../../new_fields/Types";
 import { emptyFunction, returnFalse, setupMoveUpEvents } from "../../../Utils";
 import { Scripting } from "../../util/Scripting";
 import { ContextMenu } from "../ContextMenu";
@@ -19,6 +19,7 @@ const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
 import React = require("react");
+import { DocumentView } from "../nodes/DocumentView";
 
 @observer
 export class CollectionTimeView extends CollectionSubView(doc => doc) {
@@ -28,14 +29,15 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) {
     componentWillUnmount() {
         this.props.Document.onChildClick = undefined;
     }
-    componentDidMount() {
-        const childDetailed = this.props.Document.childDetailed; // bcz: needs to be here to make sure the childDetailed layout template has been loaded when the first item is clicked;
-        const childText = "const alias = getAlias(this); Doc.ApplyTemplateTo(thisContainer.childDetailed, alias, 'layout_detailView'); alias.layoutKey='layout_detailedView'; alias.dropAction='alias'; alias.removeDropProperties=new List<string>(['dropAction']); useRightSplit(alias, shiftKey); ";
+    async componentDidMount() {
+        const childText = "const alias = getAlias(this); switchView(alias, thisContainer.childDetailView); alias.dropAction='alias'; alias.removeDropProperties=new List<string>(['dropAction']); useRightSplit(alias, shiftKey); ";
         this.props.Document.onChildClick = ScriptField.MakeScript(childText, { this: Doc.name, heading: "string", thisContainer: Doc.name, shiftKey: "boolean" });
         this.props.Document._fitToBox = true;
         if (!this.props.Document.onViewDefClick) {
             this.props.Document.onViewDefDivClick = ScriptField.MakeScript("pivotColumnClick(this,payload)", { payload: "any" });
         }
+        this.props.Document.childDetailView = Cast(this.props.Document.childDetailView, Doc, null) ||// bcz: needs to be here to make sure the childDetailView layout template has been loaded when the first item is clicked;
+            DocumentView.findTemplate("detailView", StrCast(this.props.Document.type), "");
     }
 
     layoutEngine = () => this._layoutEngine;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 23fb259fc..b96ee4bc4 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -754,7 +754,7 @@ export class CollectionTreeView extends CollectionSubView(Document, undefined as
                     }));
 
                 Document.childLayout = heroView;
-                Document.childDetailed = detailView;
+                Document.childDetailView = detailView;
                 Document._viewType = CollectionViewType.Time;
                 Document._forceActive = true;
                 Document._pivotField = "company";
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 8cc5146d5..f94277862 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -232,8 +232,8 @@ export class CollectionView extends Touchable<FieldViewProps> {
             if (this.props.Document.childLayout instanceof Doc) {
                 layoutItems.push({ description: "View Child Layout", event: () => this.props.addDocTab(this.props.Document.childLayout as Doc, "onRight"), icon: "project-diagram" });
             }
-            if (this.props.Document.childDetailed instanceof Doc) {
-                layoutItems.push({ description: "View Child Detailed Layout", event: () => this.props.addDocTab(this.props.Document.childDetailed as Doc, "onRight"), icon: "project-diagram" });
+            if (this.props.Document.childDetailView instanceof Doc) {
+                layoutItems.push({ description: "View Child Detailed Layout", event: () => this.props.addDocTab(this.props.Document.childDetailView as Doc, "onRight"), icon: "project-diagram" });
             }
             layoutItems.push({ description: `${this.props.Document.isInPlaceContainer ? "Unset" : "Set"} inPlace Container`, event: () => this.props.Document.isInPlaceContainer = !this.props.Document.isInPlaceContainer, icon: "project-diagram" });
 
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index ba95dce00..e494c337a 100644
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ b/src/client/views/collections/CollectionViewChromes.tsx
@@ -48,8 +48,8 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
     };
     _narrativeCommand = {
         params: ["target", "source"], title: "=> click item view",
-        script: "this.target.childDetailed = getDocTemplate(this.source?.[0])",
-        immediate: (source: Doc[]) => this.target.childDetailed = Doc.getDocTemplate(source?.[0]),
+        script: "this.target.childDetailView = getDocTemplate(this.source?.[0])",
+        immediate: (source: Doc[]) => this.target.childDetailView = Doc.getDocTemplate(source?.[0]),
         initialize: emptyFunction,
     };
     _contentCommand = {
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index cc3c39154..5b6478e66 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -541,7 +541,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     deleteClicked = (): void => { SelectionManager.DeselectAll(); this.props.removeDocument?.(this.props.Document); }
 
     // applies a custom template to a document.  the template is identified by it's short name (e.g, slideView not layout_slideView)
-    static makeCustomViewClicked = (doc: Doc, creator: (documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc, templateSignature: string = "custom", docLayoutTemplate?: Doc) => {
+    static makeCustomViewClicked = (doc: Doc, creator: Opt<(documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc>, templateSignature: string = "custom", docLayoutTemplate?: Doc) => {
         const batch = UndoManager.StartBatch("makeCustomViewClicked");
         runInAction(() => {
             doc.layoutKey = "layout_" + templateSignature;
@@ -563,7 +563,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         !docLayoutTemplate && allTemplates.forEach(tempDoc => StrCast(tempDoc.title) === templateName && (docLayoutTemplate = tempDoc));
         return docLayoutTemplate;
     }
-    static createCustomView = (doc: Doc, creator: (documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc, templateSignature: string = "custom", docLayoutTemplate?: Doc) => {
+    static createCustomView = (doc: Doc, creator: Opt<(documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc>, templateSignature: string = "custom", docLayoutTemplate?: Doc) => {
         const templateName = templateSignature.replace(/\(.*\)/, "");
         docLayoutTemplate = docLayoutTemplate || DocumentView.findTemplate(templateName, StrCast(doc.type), templateSignature);
 
@@ -584,10 +584,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         } else if (doc.data instanceof ImageField) {
             fieldTemplate = Docs.Create.ImageDocument("http://www.cs.brown.edu", options);
         }
-        const docTemplate = docLayoutTemplate || creator(fieldTemplate ? [fieldTemplate] : [], { title: customName + "(" + doc.title + ")", isTemplateDoc: true, _width: _width + 20, _height: Math.max(100, _height + 45) });
+        const docTemplate = docLayoutTemplate || creator?.(fieldTemplate ? [fieldTemplate] : [], { title: customName + "(" + doc.title + ")", isTemplateDoc: true, _width: _width + 20, _height: Math.max(100, _height + 45) });
 
         fieldTemplate && Doc.MakeMetadataFieldTemplate(fieldTemplate, Doc.GetProto(docTemplate));
-        Doc.ApplyTemplateTo(docTemplate, doc, customName, undefined);
+        docTemplate && Doc.ApplyTemplateTo(docTemplate, doc, customName, undefined);
     }
 
     @undoBatch
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 92abb7a71..bcf0d1aec 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -603,14 +603,6 @@ export namespace Doc {
         return undefined;
     }
     export function ApplyTemplateTo(templateDoc: Doc, target: Doc, targetKey: string, titleTarget: string | undefined) {
-        if (!templateDoc) {
-            target.layout = undefined;
-            target._nativeWidth = undefined;
-            target._nativeHeight = undefined;
-            target.type = undefined;
-            return;
-        }
-
         if (!Doc.AreProtosEqual(target[targetKey] as Doc, templateDoc)) {
             if (target.resolvedDataDoc) {
                 target[targetKey] = new PrefetchProxy(templateDoc);
diff --git a/src/new_fields/documentSchemas.ts b/src/new_fields/documentSchemas.ts
index b11941f40..bc63e9df8 100644
--- a/src/new_fields/documentSchemas.ts
+++ b/src/new_fields/documentSchemas.ts
@@ -74,7 +74,7 @@ export const positionSchema = createSchema({
 
 export const collectionSchema = createSchema({
     childLayout: Doc, // layout template for children of a collecion
-    childDetailed: Doc, // layout template to apply to a child when its clicked on in a collection and opened (requires onChildClick or other script to use this field)
+    childDetailView: Doc, // layout template to apply to a child when its clicked on in a collection and opened (requires onChildClick or other script to use this field)
     onChildClick: ScriptField, // script to run for each child when its clicked
     onCheckedClick: ScriptField, // script to run when a checkbox is clicked next to a child in a tree view
 });
-- 
cgit v1.2.3-70-g09d2


From a9613d73947ee9b000c695b8f3d7685feed96a27 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 14 Apr 2020 17:37:20 -0400
Subject: fixed goldenlayout borders.  made filter flyout semistransparent.
 fixed map to stay inbounds when filter is expanded.

---
 src/client/goldenLayout.js                          | 4 +++-
 src/client/views/collections/CollectionMapView.scss | 3 +++
 src/client/views/collections/CollectionView.scss    | 1 -
 src/client/views/collections/CollectionView.tsx     | 2 +-
 4 files changed, 7 insertions(+), 3 deletions(-)

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

diff --git a/src/client/goldenLayout.js b/src/client/goldenLayout.js
index b510385ff..2d4283b02 100644
--- a/src/client/goldenLayout.js
+++ b/src/client/goldenLayout.js
@@ -1551,7 +1551,7 @@
         },
         dimensions: {
             borderWidth: 5,
-            borderGrabWidth: 15,
+            borderGrabWidth: 5,
             minItemHeight: 10,
             minItemWidth: 10,
             headerHeight: 20,
@@ -2796,11 +2796,13 @@
             if (this._isVertical) {
                 dragHandle.css('top', -handleExcessPos);
                 dragHandle.css('height', this._size + handleExcessSize);
+                element.css('cursor', 'row-resize');
                 element.addClass('lm_vertical');
                 element['height'](this._size);
             } else {
                 dragHandle.css('left', -handleExcessPos);
                 dragHandle.css('width', this._size + handleExcessSize);
+                element.css('cursor', 'col-resize');
                 element.addClass('lm_horizontal');
                 element['width'](this._size);
             }
diff --git a/src/client/views/collections/CollectionMapView.scss b/src/client/views/collections/CollectionMapView.scss
index cb58b1750..7e4f9a0f4 100644
--- a/src/client/views/collections/CollectionMapView.scss
+++ b/src/client/views/collections/CollectionMapView.scss
@@ -4,6 +4,9 @@
     .collectionMapView-contents {
         width: 100%;
         height: 100%;
+        > div {
+            position: unset !important; // when the sidebar filter flys out, this prevents the map from extending outside the document box
+        }
     }
 }
 
diff --git a/src/client/views/collections/CollectionView.scss b/src/client/views/collections/CollectionView.scss
index b92c5fdd1..a0b73b90f 100644
--- a/src/client/views/collections/CollectionView.scss
+++ b/src/client/views/collections/CollectionView.scss
@@ -11,7 +11,6 @@
     height: 100%;
     overflow: hidden; // bcz: used to be 'auto' which would create scrollbars when there's a floating doc that's not visible. not sure if that's better, but the scrollbars are annoying...
 
-
     .collectionTimeView-dragger {
         background-color: lightgray;
         height: 40px;
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index f94277862..13a657800 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -389,7 +389,7 @@ export class CollectionView extends Touchable<FieldViewProps> {
             return false;
         }), returnFalse, action(() => this._facetWidth = this.facetWidth() < 15 ? Math.min(this.props.PanelWidth() - 25, 200) : 0));
     }
-    filterBackground = () => "dimGray";
+    filterBackground = () => "rgba(105, 105, 105, 0.432)";
     get ignoreFields() { return ["_docFilters", "_docRangeFilters"]; } // this makes the tree view collection ignore these filters (otherwise, the filters would filter themselves)
     @computed get scriptField() {
         const scriptText = "setDocFilter(containingTreeView, heading, this.title, checked)";
-- 
cgit v1.2.3-70-g09d2

