From 47214818a4a6f423ed65ab90d2a5876bde370dc8 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Wed, 22 Jul 2020 10:22:27 -0500
Subject: framework for properties panel

---
 .../collectionFreeForm/PropertiesView.tsx          | 38 ++++++++++++++++++++++
 1 file changed, 38 insertions(+)
 create mode 100644 src/client/views/collections/collectionFreeForm/PropertiesView.tsx

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

diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
new file mode 100644
index 000000000..4306453ea
--- /dev/null
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -0,0 +1,38 @@
+import React = require("react");
+import { observer } from "mobx-react";
+import "./PropertiesView.scss";
+import { observable, action } from "mobx";
+import { Doc } from "../../../../fields/Doc";
+import { DocumentView } from "../../nodes/DocumentView";
+
+
+// interface PropertiesViewProps {
+//     document: Doc;
+//     dataDoc: Doc;
+//     docView: DocumentView;
+//     width: number;
+// }
+
+@observer
+export class PropertiesView extends React.Component<{}> {
+
+    render() {
+        return <div className="propertiesView" >
+            <div className="propertiesView-title">
+                Properties
+            </div>
+            <div className="propertiesView-name">
+                Properties
+            </div>
+            <div className="propertiesView-settings">
+                Settings
+            </div>
+            <div className="propertiesView-fields">
+                Fields
+            </div>
+            <div className="propertiesView-layout">
+                Layout
+            </div>
+        </div>;
+    }
+} 
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 5b025537f60ef9222c0203db378c0298cd3dc86f Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Wed, 22 Jul 2020 12:57:05 -0500
Subject: adding fields to properties column

---
 src/client/util/CurrentUserUtils.ts                |  8 +--
 src/client/views/EditableView.tsx                  |  2 +-
 src/client/views/MainView.scss                     |  5 +-
 src/client/views/collections/CollectionView.tsx    |  2 +-
 .../collectionFreeForm/PropertiesView.scss         | 43 +++++++++++++---
 .../collectionFreeForm/PropertiesView.tsx          | 60 +++++++++++++++++-----
 6 files changed, 93 insertions(+), 27 deletions(-)

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

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 088e20a3e..1dd25ae30 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -660,7 +660,7 @@ export class CurrentUserUtils {
 
         CurrentUserUtils.workspaceStack = new PrefetchProxy(Docs.Create.TreeDocument([workspaces], {
             title: " ", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias",
-            treeViewTruncateTitleWidth: 150, hideFilterView: true,
+            treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false,
             lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same"
         })) as any as Doc;
 
@@ -679,7 +679,7 @@ export class CurrentUserUtils {
 
         CurrentUserUtils.catalogStack = new PrefetchProxy(Docs.Create.TreeDocument([catalog], {
             title: " ", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias",
-            treeViewTruncateTitleWidth: 150, hideFilterView: true,
+            treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false,
             lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same"
         })) as any as Doc;
 
@@ -703,7 +703,7 @@ export class CurrentUserUtils {
 
         CurrentUserUtils.closedStack = new PrefetchProxy(Docs.Create.TreeDocument([recentlyClosed], {
             title: " ", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias",
-            treeViewTruncateTitleWidth: 150, hideFilterView: true,
+            treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false,
             lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same"
         })) as any as Doc;
 
@@ -718,7 +718,7 @@ export class CurrentUserUtils {
         if (doc["tabs-button-library"] === undefined) {
             const libraryStack = new PrefetchProxy(Docs.Create.TreeDocument([workspaces, documents, recentlyClosed, doc], {
                 title: "Library", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias",
-                treeViewTruncateTitleWidth: 150, hideFilterView: true,
+                treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false,
                 lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same"
             })) as any as Doc;
             doc["tabs-button-library"] = new PrefetchProxy(Docs.Create.ButtonDocument({
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 25a87ab56..259a803a2 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -192,7 +192,7 @@ export class EditableView extends React.Component<EditableProps> {
             return (this.props.contents instanceof ObjectField ? (null) :
                 <div className={`editableView-container-editing${this.props.oneLine ? "-oneLine" : ""}`}
                     ref={this._ref}
-                    style={{ display: this.props.display, minHeight: "20px", height: `${this.props.height ? this.props.height : "auto"}`, maxHeight: `${this.props.maxHeight}` }}
+                    style={{ display: this.props.display, minHeight: "17px", whiteSpace: "nowrap", height: `${this.props.height ? this.props.height : "auto"}`, maxHeight: `${this.props.maxHeight}` }}
                     onClick={this.onClick} placeholder={this.props.placeholder}>
                     <span style={{
                         fontStyle: this.props.fontStyle, fontSize: this.props.fontSize,
diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index 9c04458fe..55280b231 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -121,6 +121,9 @@
     padding: 20px;
     padding-right: 50px;
 
+    overflow-y: scroll;
+    overflow-x: hidden;
+
     .mainView-menuPanel-button {
         width: 45px;
         height: 45px;
@@ -174,7 +177,7 @@
         background-color: dimgray;
         border-radius: 100%;
         transform-origin: top left;
-        margin-bottom: 23px;
+        margin-bottom: 20px;
         margin-top: 5px;
 
         margin-right: 25px;
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 44d22dd5d..616e7995d 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -588,7 +588,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
                 width: `${this.propertiesWidth()}px`,
                 overflow: this.propertiesWidth() < 15 ? "hidden" : undefined
             }}>
-                <PropertiesView />
+                <PropertiesView document={this.dataDoc} />
             </div>;
     }
 
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index d4cc53bfa..bb5b80abd 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -1,32 +1,59 @@
 .propertiesView {
 
-    background-color: rgb(168, 168, 168);
+    background-color: rgb(205, 205, 205);
     height: 100%;
     z-index: 1;
+    font-family: "Noto Sans";
+    cursor: auto;
+
+    //overflow-y: scroll;
 
     .propertiesView-title {
-        background-color: rgb(134, 134, 134);
-        border-top: 1px solid black;
-        border-bottom: 1px solid black;
+        background-color: rgb(159, 159, 159);
+        text-align: center;
+        font-size: 18px;
+        font-weight: bold;
+        padding-top: 12px;
+        padding-bottom: 12px;
     }
 
     .propertiesView-name {
-        border-top: 1px solid black;
         border-bottom: 1px solid black;
+        padding: 8.5px;
+        font-size: 12.5px;
     }
 
     .propertiesView-settings {
-        border-top: 1px solid black;
         border-bottom: 1px solid black;
+        padding: 8.5px;
+        font-size: 12.5px;
+        font-weight: bold;
     }
 
     .propertiesView-fields {
-        border-top: 1px solid black;
         border-bottom: 1px solid black;
+        padding: 8.5px;
+
+        .propertiesView-fields-title {
+            font-size: 12.5px;
+            font-weight: bold;
+            padding-bottom: 7px;
+        }
+
+        .propertiesView-fields-content {
+            font-size: 10px;
+            margin-left: 5px;
+
+            &:hover {
+                cursor: pointer;
+            }
+        }
     }
 
     .propertiesView-layout {
-        border-top: 1px solid black;
         border-bottom: 1px solid black;
+        padding: 8.5px;
+        font-size: 12.5px;
+        font-weight: bold;
     }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 4306453ea..bc78fccdf 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -1,20 +1,54 @@
 import React = require("react");
 import { observer } from "mobx-react";
 import "./PropertiesView.scss";
-import { observable, action } from "mobx";
-import { Doc } from "../../../../fields/Doc";
+import { observable, action, computed } from "mobx";
+import { Doc, Field, DocListCast } from "../../../../fields/Doc";
 import { DocumentView } from "../../nodes/DocumentView";
+import { ComputedField } from "../../../../fields/ScriptField";
+import { EditableView } from "../../EditableView";
+import { KeyValueBox } from "../../nodes/KeyValueBox";
+import { Cast } from "../../../../fields/Types";
+import { listSpec } from "../../../../fields/Schema";
 
 
-// interface PropertiesViewProps {
-//     document: Doc;
-//     dataDoc: Doc;
-//     docView: DocumentView;
-//     width: number;
-// }
+interface PropertiesViewProps {
+    document: Doc;
+    //dataDoc: Doc;
+    //docView: DocumentView;
+}
 
 @observer
-export class PropertiesView extends React.Component<{}> {
+export class PropertiesView extends React.Component<PropertiesViewProps> {
+
+    @computed get expandedField() {
+        const ids: { [key: string]: string } = {};
+        const doc = this.props.document;
+        doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key));
+
+        const rows: JSX.Element[] = [];
+        for (const key of Object.keys(ids).slice().sort()) {
+            const contents = doc[key];
+            let contentElement: (JSX.Element | null)[] | JSX.Element = [];
+            contentElement = <EditableView key="editableView"
+                contents={contents !== undefined ? Field.toString(contents as Field) : "null"}
+                height={13}
+                fontSize={10}
+                GetValue={() => Field.toKeyValueString(doc, key)}
+                SetValue={(value: string) => KeyValueBox.SetField(doc, key, value, true)}
+            />;
+
+            rows.push(<div style={{ display: "flex", overflowY: "visible", marginBottom: "-1px" }} key={key}>
+                <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key + ":"}</span>
+                &nbsp;
+                {contentElement}
+            </div>);
+        }
+        return rows;
+    }
+
+    @computed get layoutPreview() {
+        return "layout";
+    }
 
     render() {
         return <div className="propertiesView" >
@@ -22,16 +56,18 @@ export class PropertiesView extends React.Component<{}> {
                 Properties
             </div>
             <div className="propertiesView-name">
-                Properties
+                Collection
             </div>
             <div className="propertiesView-settings">
                 Settings
             </div>
             <div className="propertiesView-fields">
-                Fields
+                <div className="propertiesView-fields-title"> Fields</div>
+                <div className="propertiesView-fields-content"> {this.expandedField} </div>
             </div>
             <div className="propertiesView-layout">
-                Layout
+                <div>Layout</div>
+                <div>{this.layoutPreview}</div>
             </div>
         </div>;
     }
-- 
cgit v1.2.3-70-g09d2


From a99cef9945c1c4f9e5ff07663fc6db5cda2dcd50 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Wed, 22 Jul 2020 16:27:27 -0500
Subject: added layout section

---
 src/client/views/collections/CollectionView.tsx    |  7 +-
 .../collectionFreeForm/PropertiesView.scss         | 15 +++-
 .../collectionFreeForm/PropertiesView.tsx          | 82 +++++++++++++++++++---
 3 files changed, 92 insertions(+), 12 deletions(-)

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

diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 616e7995d..eec68f9fc 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -588,7 +588,12 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
                 width: `${this.propertiesWidth()}px`,
                 overflow: this.propertiesWidth() < 15 ? "hidden" : undefined
             }}>
-                <PropertiesView document={this.dataDoc} />
+                <PropertiesView dataDoc={this.dataDoc} Document={this.props.Document}
+                    width={this._propertiesWidth}
+                    height={this.props.PanelHeight()}
+                    renderDepth={this.props.renderDepth}
+                    ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+                />
             </div>;
     }
 
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index bb5b80abd..e81b1eeb4 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -51,9 +51,18 @@
     }
 
     .propertiesView-layout {
-        border-bottom: 1px solid black;
         padding: 8.5px;
-        font-size: 12.5px;
-        font-weight: bold;
+
+        .propertiesView-layout-title {
+            font-weight: bold;
+            font-size: 12.5px;
+            padding-bottom: 7px;
+        }
+
+        .propertiesView-layout-content {
+            margin-left: 5px;
+            overflow: hidden;
+        }
+
     }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index bc78fccdf..27b0dbd9e 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -2,27 +2,58 @@ import React = require("react");
 import { observer } from "mobx-react";
 import "./PropertiesView.scss";
 import { observable, action, computed } from "mobx";
-import { Doc, Field, DocListCast } from "../../../../fields/Doc";
+import { Doc, Field, DocListCast, WidthSym, HeightSym } from "../../../../fields/Doc";
 import { DocumentView } from "../../nodes/DocumentView";
 import { ComputedField } from "../../../../fields/ScriptField";
 import { EditableView } from "../../EditableView";
 import { KeyValueBox } from "../../nodes/KeyValueBox";
-import { Cast } from "../../../../fields/Types";
+import { Cast, StrCast, NumCast } from "../../../../fields/Types";
 import { listSpec } from "../../../../fields/Schema";
+import { ContentFittingDocumentView } from "../../nodes/ContentFittingDocumentView";
+import { returnFalse, returnOne, emptyFunction, emptyPath, returnTrue, returnZero, returnEmptyFilter, Utils } from "../../../../Utils";
+import { Id } from "../../../../fields/FieldSymbols";
+import { Transform } from "../../../util/Transform";
 
 
 interface PropertiesViewProps {
-    document: Doc;
-    //dataDoc: Doc;
+    dataDoc: Doc;
+    Document: Doc;
+    width: number;
+    height: number;
+    renderDepth: number;
+    ScreenToLocalTransform: () => Transform;
     //docView: DocumentView;
 }
 
 @observer
 export class PropertiesView extends React.Component<PropertiesViewProps> {
 
+    @computed get MAX_EMBED_HEIGHT() { return 200; }
+
+    rtfWidth = () => Math.min(this.props.Document?.[WidthSym](), this.props.width - 20);
+    rtfHeight = () => this.rtfWidth() <= this.props.Document?.[WidthSym]() ? Math.min(this.props.Document?.[HeightSym](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT;
+
+    docWidth = () => {
+        const layoutDoc = this.props.Document;
+        const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]());
+        if (aspect) return Math.min(layoutDoc[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT / aspect, this.props.width - 20));
+        return NumCast(layoutDoc._nativeWidth) ? Math.min(layoutDoc[WidthSym](), this.props.width - 20) : this.props.width - 20;
+    }
+    docHeight = () => {
+        const layoutDoc = this.props.Document;
+        return Math.max(70, Math.min(this.MAX_EMBED_HEIGHT, (() => {
+            const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]());
+            if (aspect) return this.docWidth() * aspect;
+            return layoutDoc._fitWidth ? (!this.props.dataDoc._nativeHeight ? NumCast(this.props.height) :
+                Math.min(this.docWidth() * NumCast(layoutDoc.scrollHeight, NumCast(layoutDoc._nativeHeight)) / NumCast(layoutDoc._nativeWidth,
+                    NumCast(this.props.height)))) :
+                NumCast(layoutDoc._height) ? NumCast(layoutDoc._height) : 50;
+        })()));
+    }
+
     @computed get expandedField() {
         const ids: { [key: string]: string } = {};
-        const doc = this.props.document;
+        const doc = this.props.dataDoc;
         doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key));
 
         const rows: JSX.Element[] = [];
@@ -47,7 +78,42 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
     @computed get layoutPreview() {
-        return "layout";
+        const layoutDoc = Doc.Layout(this.props.Document);
+        const panelHeight = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : this.docHeight;
+        const panelWidth = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : this.docWidth;
+        return <div style={{ display: "inline-block", height: panelHeight() }} key={this.props.dataDoc[Id]}>
+            <ContentFittingDocumentView
+                Document={layoutDoc}
+                DataDoc={this.props.dataDoc}
+                LibraryPath={emptyPath}
+                renderDepth={this.props.renderDepth + 1}
+                rootSelected={returnFalse}
+                treeViewDoc={undefined}
+                backgroundColor={() => "lightgrey"}
+                fitToBox={false}
+                FreezeDimensions={true}
+                NativeWidth={layoutDoc.type ===
+                    StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : returnZero}
+                NativeHeight={layoutDoc.type ===
+                    StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : returnZero}
+                PanelWidth={panelWidth}
+                PanelHeight={panelHeight}
+                focus={returnFalse}
+                ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+                docFilters={returnEmptyFilter}
+                ContainingCollectionDoc={undefined}
+                ContainingCollectionView={undefined}
+                addDocument={returnFalse}
+                moveDocument={undefined}
+                removeDocument={returnFalse}
+                parentActive={() => false}
+                whenActiveChanged={emptyFunction}
+                addDocTab={returnFalse}
+                pinToPres={emptyFunction}
+                bringToFront={returnFalse}
+                ContentScaling={returnOne}
+            />
+        </div>;
     }
 
     render() {
@@ -66,8 +132,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 <div className="propertiesView-fields-content"> {this.expandedField} </div>
             </div>
             <div className="propertiesView-layout">
-                <div>Layout</div>
-                <div>{this.layoutPreview}</div>
+                <div className="propertiesView-layout-title" >Layout</div>
+                <div className="propertiesView-layout-content">{this.layoutPreview}</div>
             </div>
         </div>;
     }
-- 
cgit v1.2.3-70-g09d2


From 66bcfb6364ca5d8b4a0fd26139966ea9d6c12f87 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Wed, 22 Jul 2020 18:07:45 -0500
Subject: adding buttons

---
 src/client/views/PropertiesButtons.scss            | 105 ++++++++
 src/client/views/PropertiesButtons.tsx             | 296 +++++++++++++++++++++
 src/client/views/collections/CollectionView.tsx    |   2 +
 .../collectionFreeForm/PropertiesView.scss         |  12 +
 .../collectionFreeForm/PropertiesView.tsx          |   8 +-
 5 files changed, 421 insertions(+), 2 deletions(-)
 create mode 100644 src/client/views/PropertiesButtons.scss
 create mode 100644 src/client/views/PropertiesButtons.tsx

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

diff --git a/src/client/views/PropertiesButtons.scss b/src/client/views/PropertiesButtons.scss
new file mode 100644
index 000000000..8dd5cec03
--- /dev/null
+++ b/src/client/views/PropertiesButtons.scss
@@ -0,0 +1,105 @@
+@import "globalCssVariables";
+
+$linkGap : 3px;
+
+.propertiesButtons-linkFlyout {
+    grid-column: 2/4;
+}
+
+.propertiesButtons-linkButton-empty:hover {
+    background: $main-accent;
+    transform: scale(1.05);
+    cursor: pointer;
+}
+
+.propertiesButtons-linkButton-nonempty:hover {
+    background: $main-accent;
+    transform: scale(1.05);
+    cursor: pointer;
+}
+
+.propertiesButtons-linkButton-empty,
+.propertiesButtons-linkButton-nonempty {
+    height: 20px;
+    width: 20px;
+    border-radius: 50%;
+    opacity: 0.9;
+    pointer-events: auto;
+    background-color: $dark-color;
+    color: $light-color;
+    text-transform: uppercase;
+    letter-spacing: 2px;
+    font-size: 75%;
+    transition: transform 0.2s;
+    text-align: center;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+
+    &:hover {
+        background: $main-accent;
+        transform: scale(1.05);
+        cursor: pointer;
+    }
+}
+
+.propertiesButtons {
+    margin-top: $linkGap;
+    grid-column: 1/4;
+    width: max-content;
+    height: auto;
+    display: flex;
+    flex-direction: row;
+}
+
+.propertiesButtons-button {
+    pointer-events: auto;
+    padding-right: 5px;
+    width: 25px;
+}
+
+.propertiesButtons-linker {
+    height: 20px;
+    width: 20px;
+    text-align: center;
+    border-radius: 50%;
+    pointer-events: auto;
+    color: $dark-color;
+    border: $dark-color 1px solid;
+    transition: 0.2s ease all;
+}
+
+.propertiesButtons-linker:hover {
+    cursor: pointer;
+    transform: scale(1.05);
+}
+
+
+@-moz-keyframes spin {
+    100% {
+        -moz-transform: rotate(360deg);
+    }
+}
+
+@-webkit-keyframes spin {
+    100% {
+        -webkit-transform: rotate(360deg);
+    }
+}
+
+@keyframes spin {
+    100% {
+        -webkit-transform: rotate(360deg);
+        transform: rotate(360deg);
+    }
+}
+
+@keyframes shadow-pulse {
+    0% {
+        box-shadow: 0 0 0 0px rgba(0, 0, 0, 0.8);
+    }
+
+    100% {
+        box-shadow: 0 0 0 10px rgba(0, 255, 0, 0);
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
new file mode 100644
index 000000000..842d0320f
--- /dev/null
+++ b/src/client/views/PropertiesButtons.tsx
@@ -0,0 +1,296 @@
+import { IconProp, library } from '@fortawesome/fontawesome-svg-core';
+import { faArrowAltCircleDown, faArrowAltCircleRight, faArrowAltCircleUp, faCheckCircle, faCloudUploadAlt, faLink, faPhotoVideo, faShare, faStopCircle, faSyncAlt, faTag, faTimes } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { action, computed, observable, runInAction } from "mobx";
+import { observer } from "mobx-react";
+import { Doc, DocListCast } from "../../fields/Doc";
+import { RichTextField } from '../../fields/RichTextField';
+import { Cast, NumCast } from "../../fields/Types";
+import { emptyFunction, setupMoveUpEvents } from "../../Utils";
+import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager';
+import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils';
+import { Docs, DocUtils } from '../documents/Documents';
+import { DragManager } from '../util/DragManager';
+import { CollectionDockingView, DockedFrameRenderer } from './collections/CollectionDockingView';
+import { ParentDocSelector } from './collections/ParentDocumentSelector';
+import './collections/ParentDocumentSelector.scss';
+import './PropertiesButtons.scss';
+import { MetadataEntryMenu } from './MetadataEntryMenu';
+import { DocumentView } from './nodes/DocumentView';
+import { GoogleRef } from "./nodes/formattedText/FormattedTextBox";
+import { TemplateMenu } from "./TemplateMenu";
+import { Template, Templates } from "./Templates";
+import React = require("react");
+import { Tooltip } from '@material-ui/core';
+const higflyout = require("@hig/flyout");
+export const { anchorPoints } = higflyout;
+export const Flyout = higflyout.default;
+
+library.add(faLink);
+library.add(faTag);
+library.add(faTimes);
+library.add(faArrowAltCircleDown);
+library.add(faArrowAltCircleUp);
+library.add(faArrowAltCircleRight);
+library.add(faStopCircle);
+library.add(faCheckCircle);
+library.add(faCloudUploadAlt);
+library.add(faSyncAlt);
+library.add(faShare);
+library.add(faPhotoVideo);
+
+const cloud: IconProp = "cloud-upload-alt";
+const fetch: IconProp = "sync-alt";
+
+enum UtilityButtonState {
+    Default,
+    OpenRight,
+    OpenExternally
+}
+
+@observer
+export class PropertiesButtons extends React.Component<{ doc: Doc }, {}> {
+    private _dragRef = React.createRef<HTMLDivElement>();
+    private _pullAnimating = false;
+    private _pushAnimating = false;
+    private _pullColorAnimating = false;
+
+    @observable private pushIcon: IconProp = "arrow-alt-circle-up";
+    @observable private pullIcon: IconProp = "arrow-alt-circle-down";
+    @observable private pullColor: string = "white";
+    @observable public isAnimatingFetch = false;
+    @observable public isAnimatingPulse = false;
+
+    @observable private openHover: UtilityButtonState = UtilityButtonState.Default;
+
+    @observable public static Instance: PropertiesButtons;
+    public static hasPushedHack = false;
+    public static hasPulledHack = false;
+
+    public startPullOutcome = action((success: boolean) => {
+        if (!this._pullAnimating) {
+            this._pullAnimating = true;
+            this.pullIcon = success ? "check-circle" : "stop-circle";
+            setTimeout(() => runInAction(() => {
+                this.pullIcon = "arrow-alt-circle-down";
+                this._pullAnimating = false;
+            }), 1000);
+        }
+    });
+
+    public startPushOutcome = action((success: boolean) => {
+        this.isAnimatingPulse = false;
+        if (!this._pushAnimating) {
+            this._pushAnimating = true;
+            this.pushIcon = success ? "check-circle" : "stop-circle";
+            setTimeout(() => runInAction(() => {
+                this.pushIcon = "arrow-alt-circle-up";
+                this._pushAnimating = false;
+            }), 1000);
+        }
+    });
+
+    public setPullState = action((unchanged: boolean) => {
+        this.isAnimatingFetch = false;
+        if (!this._pullColorAnimating) {
+            this._pullColorAnimating = true;
+            this.pullColor = unchanged ? "lawngreen" : "red";
+            setTimeout(this.clearPullColor, 1000);
+        }
+    });
+
+    private clearPullColor = action(() => {
+        this.pullColor = "white";
+        this._pullColorAnimating = false;
+    });
+
+    //get view0() { return this.props.views()?.[0]; }
+
+    @computed
+    get considerGoogleDocsPush() {
+        const targetDoc = this.props.doc;
+        const published = targetDoc && Doc.GetProto(targetDoc)[GoogleRef] !== undefined;
+        const animation = this.isAnimatingPulse ? "shadow-pulse 1s linear infinite" : "none";
+        return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{`${published ? "Push" : "Publish"} to Google Docs`}</div></>}>
+            <div
+                className="propertiesButtons-linker"
+                style={{ animation }}
+                onClick={async () => {
+                    await GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken();
+                    !published && runInAction(() => this.isAnimatingPulse = true);
+                    PropertiesButtons.hasPushedHack = false;
+                    targetDoc[Pushes] = NumCast(targetDoc[Pushes]) + 1;
+                }}>
+                <FontAwesomeIcon className="documentdecorations-icon" icon={published ? (this.pushIcon as any) : cloud} size={published ? "sm" : "xs"} />
+            </div></Tooltip>;
+    }
+
+    @computed
+    get considerGoogleDocsPull() {
+        const targetDoc = this.props.doc;
+        const dataDoc = targetDoc && Doc.GetProto(targetDoc);
+        const animation = this.isAnimatingFetch ? "spin 0.5s linear infinite" : "none";
+
+        const title = (() => {
+            switch (this.openHover) {
+                default:
+                case UtilityButtonState.Default: return `${!dataDoc?.unchanged ? "Pull from" : "Fetch"} Google Docs`;
+                case UtilityButtonState.OpenRight: return "Open in Right Split";
+                case UtilityButtonState.OpenExternally: return "Open in new Browser Tab";
+            }
+        })();
+
+        return !targetDoc || !dataDoc || !dataDoc[GoogleRef] ? (null) : <Tooltip
+            title={<><div className="dash-tooltip">{title}</div></>}>
+            <div className="propertiesButtons-linker"
+                style={{ backgroundColor: this.pullColor }}
+                onPointerEnter={action(e => {
+                    if (e.altKey) {
+                        this.openHover = UtilityButtonState.OpenExternally;
+                    } else if (e.shiftKey) {
+                        this.openHover = UtilityButtonState.OpenRight;
+                    }
+                })}
+                onPointerLeave={action(() => this.openHover = UtilityButtonState.Default)}
+                onClick={async e => {
+                    const googleDocUrl = `https://docs.google.com/document/d/${dataDoc[GoogleRef]}/edit`;
+                    if (e.shiftKey) {
+                        e.preventDefault();
+                        let googleDoc = await Cast(dataDoc.googleDoc, Doc);
+                        if (!googleDoc) {
+                            const options = { _width: 600, _nativeWidth: 960, _nativeHeight: 800, isAnnotating: false, UseCors: false };
+                            googleDoc = Docs.Create.WebDocument(googleDocUrl, options);
+                            dataDoc.googleDoc = googleDoc;
+                        }
+                        CollectionDockingView.AddRightSplit(googleDoc);
+                    } else if (e.altKey) {
+                        e.preventDefault();
+                        window.open(googleDocUrl);
+                    } else {
+                        this.clearPullColor();
+                        PropertiesButtons.hasPulledHack = false;
+                        targetDoc[Pulls] = NumCast(targetDoc[Pulls]) + 1;
+                        dataDoc.unchanged && runInAction(() => this.isAnimatingFetch = true);
+                    }
+                }}>
+                <FontAwesomeIcon className="documentdecorations-icon" size="sm"
+                    style={{ WebkitAnimation: animation, MozAnimation: animation }}
+                    icon={(() => {
+                        switch (this.openHover) {
+                            default:
+                            case UtilityButtonState.Default: return dataDoc.unchanged === false ? (this.pullIcon as any) : fetch;
+                            case UtilityButtonState.OpenRight: return "arrow-alt-circle-right";
+                            case UtilityButtonState.OpenExternally: return "share";
+                        }
+                    })()}
+                />
+            </div></Tooltip>;
+    }
+    @computed
+    get pinButton() {
+        const targetDoc = this.props.doc;
+        const isPinned = targetDoc && Doc.isDocPinned(targetDoc);
+        return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}</div></>}>
+            <div className="propertiesButtons-linker"
+                style={{ backgroundColor: isPinned ? "black" : "white", color: isPinned ? "white" : "black" }}
+                onClick={e => DockedFrameRenderer.PinDoc(targetDoc, isPinned)}>
+                <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin"
+                />
+            </div></Tooltip>;
+    }
+
+    @computed
+    get metadataButton() {
+        //const view0 = this.view0;
+        return <Tooltip title={<><div className="dash-tooltip">Show metadata panel</div></>}>
+            <div className="propertiesButtons-linkFlyout">
+                <Flyout anchorPoint={anchorPoints.LEFT_TOP}
+                    content={<MetadataEntryMenu docs={[this.props.doc]} suggestWithFunction />  /* tfs: @bcz This might need to be the data document? */}>
+                    <div className={"propertiesButtons-linkButton-" + "empty"} onPointerDown={e => e.stopPropagation()} >
+                        {<FontAwesomeIcon className="documentdecorations-icon" icon="tag" size="sm" />}
+                    </div>
+                </Flyout>
+            </div></Tooltip>;
+    }
+
+    // @computed
+    // get contextButton() {
+    //     return <ParentDocSelector Document={this.Document} addDocTab={(doc, where) => {
+    //         where === "onRight" ? CollectionDockingView.AddRightSplit(doc) :
+    //                 this.props.doc.props.addDocTab(doc, "onRight");
+    //         return true;
+    //     }} />;
+    // }
+
+    @observable _aliasDown = false;
+    onAliasButtonDown = (e: React.PointerEvent): void => {
+        //setupMoveUpEvents(this, e, this.onAliasButtonMoved, emptyFunction, emptyFunction);
+
+    }
+
+    // onAliasButtonMoved = () => {
+    //     if (this._dragRef.current) {
+    //         const dragDocView = this.props.doc!;
+    //         if (dragDocView.props){
+    //             const dragData = new DragManager.DocumentDragData([dragDocView.props.Document]);
+    //             const [left, top] = dragDocView.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
+    //             dragData.dropAction = "alias";
+    //             DragManager.StartDocumentDrag([dragDocView.ContentDiv!], dragData, left, top, {
+    //             offsetX: dragData.offset[0],
+    //             offsetY: dragData.offset[1],
+    //             hideSource: false
+    //         });
+    //         return true;
+    //         }
+
+    //     }
+    //     return false;
+    // }
+
+    // @computed
+    // get templateButton() {
+    //     //const view0 = this.view0;
+    //     const templates: Map<Template, boolean> = new Map();
+    //     //const views = this.props.views();
+    //     Array.from(Object.values(Templates.TemplateList)).map(template =>
+    //         templates.set(template, views.reduce((checked, doc) => checked || doc?.props.Document["_show" + template.Name] ? true : false, false as boolean)));
+    //     return !this.props.doc ? (null) :
+    //         <Tooltip title={<><div className="dash-tooltip">Tap: Customize layout.  Drag: Create alias</div></>}>
+    //             <div className="propertiesButtons-linkFlyout" ref={this._dragRef}>
+    //                 <Flyout anchorPoint={anchorPoints.LEFT_TOP} onOpen={action(() => this._aliasDown = true)} onClose={action(() => this._aliasDown = false)}
+    //                     content={!this._aliasDown ? (null) : <TemplateMenu docViews={views.filter(v => v).map(v => v as DocumentView)} templates={templates} />}>
+    //                     <div className={"propertiesButtons-linkButton-empty"} ref={this._dragRef} onPointerDown={this.onAliasButtonDown} >
+    //                         {<FontAwesomeIcon className="documentdecorations-icon" icon="edit" size="sm" />}
+    //                     </div>
+    //                 </Flyout>
+    //             </div></Tooltip>;
+    // }
+
+    render() {
+        if (!this.props.doc) return (null);
+
+        const isText = this.props.doc[Doc.LayoutFieldKey(this.props.doc)] instanceof RichTextField;
+        const considerPull = isText && this.considerGoogleDocsPull;
+        const considerPush = isText && this.considerGoogleDocsPush;
+        return <div className="propertiesButtons">
+            {/* <div className="propertiesButtons-button">
+                {this.templateButton}
+            </div> */}
+            <div className="propertiesButtons-button">
+                {this.metadataButton}
+            </div>
+            {/* <div className="propertiesButtons-button">
+                {this.contextButton}
+            </div> */}
+            <div className="propertiesButtons-button">
+                {this.pinButton}
+            </div>
+            <div className="propertiesButtons-button" style={{ display: !considerPush ? "none" : "" }}>
+                {this.considerGoogleDocsPush}
+            </div>
+            <div className="propertiesButtons-button" style={{ display: !considerPull ? "none" : "" }}>
+                {this.considerGoogleDocsPull}
+            </div>
+        </div>;
+    }
+}
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index eec68f9fc..853321d3c 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -50,6 +50,7 @@ import './CollectionView.scss';
 import CollectionMenu from './CollectionMenu';
 import { SharingPermissions } from '../../util/SharingManager';
 import { PropertiesView } from './collectionFreeForm/PropertiesView';
+import { DocumentView } from '../nodes/DocumentView';
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -589,6 +590,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
                 overflow: this.propertiesWidth() < 15 ? "hidden" : undefined
             }}>
                 <PropertiesView dataDoc={this.dataDoc} Document={this.props.Document}
+                    docView={CollectionView as unknown as DocumentView}
                     width={this._propertiesWidth}
                     height={this.props.PanelHeight()}
                     renderDepth={this.props.renderDepth}
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index e81b1eeb4..98eae1ac7 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -28,6 +28,18 @@
         padding: 8.5px;
         font-size: 12.5px;
         font-weight: bold;
+
+        .propertiesView-settings-title {
+            font-weight: bold;
+            font-size: 12.5px;
+            padding-bottom: 7px;
+        }
+
+        .propertiesView-settings-content {
+            margin-left: 5px;
+            padding-bottom: 10px;
+        }
+
     }
 
     .propertiesView-fields {
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 27b0dbd9e..5242aa8fd 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -13,6 +13,7 @@ import { ContentFittingDocumentView } from "../../nodes/ContentFittingDocumentVi
 import { returnFalse, returnOne, emptyFunction, emptyPath, returnTrue, returnZero, returnEmptyFilter, Utils } from "../../../../Utils";
 import { Id } from "../../../../fields/FieldSymbols";
 import { Transform } from "../../../util/Transform";
+import { PropertiesButtons } from "../../PropertiesButtons";
 
 
 interface PropertiesViewProps {
@@ -22,7 +23,7 @@ interface PropertiesViewProps {
     height: number;
     renderDepth: number;
     ScreenToLocalTransform: () => Transform;
-    //docView: DocumentView;
+    docView: DocumentView;
 }
 
 @observer
@@ -125,7 +126,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 Collection
             </div>
             <div className="propertiesView-settings">
-                Settings
+                <div className="propertiesView-settings-title"> Settings</div>
+                <div className="propertiesView-settings-content">
+                    <PropertiesButtons doc={this.props.Document} />
+                </div>
             </div>
             <div className="propertiesView-fields">
                 <div className="propertiesView-fields-title"> Fields</div>
-- 
cgit v1.2.3-70-g09d2


From 831fbc76ec1c6e9829da547cdef791ac087677d9 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Thu, 23 Jul 2020 11:08:54 -0500
Subject: moved right panel into mainview

---
 src/client/util/SelectionManager.ts                |  24 +++
 src/client/views/MainView.scss                     |  38 ++++
 src/client/views/MainView.tsx                      |  65 ++++++-
 src/client/views/PropertiesButtons.tsx             |  39 +++--
 src/client/views/collections/CollectionView.scss   |  34 ----
 src/client/views/collections/CollectionView.tsx    |  49 +-----
 .../collectionFreeForm/PropertiesView.tsx          | 193 +++++++++++++--------
 7 files changed, 262 insertions(+), 180 deletions(-)

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

diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 9a968aeda..6fb758eac 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -12,9 +12,14 @@ export namespace SelectionManager {
 
         @observable IsDragging: boolean = false;
         SelectedDocuments: ObservableMap<DocumentView, boolean> = new ObservableMap();
+
+        @observable public lastSelection: DocumentView | undefined;
+
         @action
         SelectDoc(docView: DocumentView, ctrlPressed: boolean): void {
 
+            this.lastSelection = docView;
+
             // if doc is not in SelectedDocuments, add it
             if (!manager.SelectedDocuments.get(docView)) {
                 if (!ctrlPressed) {
@@ -33,6 +38,15 @@ export namespace SelectionManager {
         }
         @action
         DeselectDoc(docView: DocumentView): void {
+
+            if (this.lastSelection === docView) {
+                const list = Array.from(manager.SelectedDocuments.keys());
+                if (list.length > 0) {
+                    this.lastSelection = list[list.length - 1];
+                } else {
+                    this.lastSelection = undefined;
+                }
+            }
             if (manager.SelectedDocuments.get(docView)) {
                 manager.SelectedDocuments.delete(docView);
                 docView.props.whenActiveChanged(false);
@@ -41,10 +55,16 @@ export namespace SelectionManager {
         }
         @action
         DeselectAll(): void {
+            this.lastSelection = undefined;
             Array.from(manager.SelectedDocuments.keys()).map(dv => dv.props.whenActiveChanged(false));
             manager.SelectedDocuments.clear();
             Doc.UserDoc().activeSelection = new List<Doc>([]);
         }
+
+        @action
+        getLast(): DocumentView | undefined {
+            return this.lastSelection;
+        }
     }
 
     const manager = new Manager();
@@ -56,6 +76,10 @@ export namespace SelectionManager {
         manager.SelectDoc(docView, ctrlPressed);
     }
 
+    export function LastSelection(): DocumentView | undefined {
+        return manager.getLast();
+    }
+
     // computed functions, such as used in IsSelected generate errors if they're called outside of a
     // reaction context.  Specifying the context with 'outsideReaction' allows an efficiency feature
     // to avoid unnecessary mobx invalidations when running inside a reaction.
diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index 55280b231..f64129600 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -102,6 +102,44 @@
     user-select: none;
 }
 
+.mainView-propertiesDragger {
+    background-color: rgb(140, 139, 139);
+    height: 55px;
+    width: 15.5px;
+    position: absolute;
+    top: 55%;
+    border: 1px black solid;
+    border-radius: 0;
+    border-top-left-radius: 10px;
+    border-bottom-left-radius: 10px;
+    border-right: unset;
+    z-index: 2;
+
+    .mainView-propertiesDragger-icon {
+        width: 10px;
+        height: 10px;
+        float: left;
+        margin-left: 3px;
+        padding-top: 19px;
+    }
+
+    &:hover {
+        cursor: pointer;
+    }
+}
+
+.mainiView-propertiesView {
+    display: flex;
+    flex-direction: column;
+    width: 200px;
+    height: 100%;
+    position: absolute;
+    right: 0;
+    top: 0;
+    border-left: solid 1px;
+    z-index: 10;
+}
+
 .mainView-flyoutContainer {
     display: flex;
     flex-direction: column;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 766626a82..88f072493 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -21,10 +21,10 @@ import { Doc, DocListCast, Field, Opt } from '../../fields/Doc';
 import { Id } from '../../fields/FieldSymbols';
 import { List } from '../../fields/List';
 import { listSpec } from '../../fields/Schema';
-import { BoolCast, Cast, FieldValue, StrCast } from '../../fields/Types';
+import { BoolCast, Cast, FieldValue, StrCast, NumCast } from '../../fields/Types';
 import { TraceMobx } from '../../fields/util';
 import { CurrentUserUtils } from '../util/CurrentUserUtils';
-import { emptyFunction, emptyPath, returnFalse, returnOne, returnZero, returnTrue, Utils, returnEmptyFilter } from '../../Utils';
+import { emptyFunction, emptyPath, returnFalse, returnOne, returnZero, returnTrue, Utils, returnEmptyFilter, setupMoveUpEvents } from '../../Utils';
 import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager';
 import { DocServer } from '../DocServer';
 import { Docs, DocumentOptions } from '../documents/Documents';
@@ -66,7 +66,9 @@ import { LinkDescriptionPopup } from './nodes/LinkDescriptionPopup';
 import FormatShapePane from "./collections/collectionFreeForm/FormatShapePane";
 import HypothesisAuthenticationManager from '../apis/HypothesisAuthenticationManager';
 import CollectionMenu from './collections/CollectionMenu';
-import { Tooltip } from '@material-ui/core';
+import { Tooltip, AccordionActions } from '@material-ui/core';
+import { PropertiesView } from './collections/collectionFreeForm/PropertiesView';
+import { SelectionManager } from '../util/SelectionManager';
 
 @observer
 export class MainView extends React.Component {
@@ -90,9 +92,24 @@ export class MainView extends React.Component {
 
     @observable public sidebarContent: any = this.userDoc?.["tabs-panelContainer"];
     @observable public panelContent: string = "none";
+    @observable public showProperties: boolean = false;
 
+    @computed get selectedDocumentView() { return SelectionManager.LastSelection(); }
+    @observable selectedDoc: Doc | undefined = this.selectedDocumentView?.props.Document;
+    @observable selectedDataDoc: Doc | undefined = this.selectedDocumentView?.props.DataDoc ? this.selectedDocumentView.props.DataDoc : this.selectedDoc;
     public isPointerDown = false;
 
+    @observable _propertiesWidth: number = 0;
+    propertiesWidth = () => Math.max(0, Math.min(this._panelWidth - 50, this._propertiesWidth));
+
+    @computed get propertiesIcon() {
+        if (this.propertiesWidth() < 10) {
+            return "chevron-left";
+        } else {
+            return "chevron-right";
+        }
+    }
+
     componentDidMount() {
         DocServer.setPlaygroundFields(["dataTransition", "_viewTransition", "_panX", "_panY", "_viewScale", "_viewType", "_chromeStatus"]); // can play with these fields on someone else's
 
@@ -216,7 +233,7 @@ export class MainView extends React.Component {
         const freeformOptions: DocumentOptions = {
             x: 0,
             y: 400,
-            _width: this._panelWidth * .7,
+            _width: this._panelWidth * .7 - this._propertiesWidth,
             _height: this._panelHeight,
             title: "Collection " + workspaceCount,
         };
@@ -282,10 +299,13 @@ export class MainView extends React.Component {
 
     @action
     onResize = (r: any) => {
-        this._panelWidth = r.offset.width;
+        this._panelWidth = r.offset.width - this._propertiesWidth;
         this._panelHeight = r.offset.height;
     }
-    getPWidth = () => this._panelWidth;
+
+    @action
+    getPWidth = () => this._panelWidth - this._propertiesWidth;
+
     getPHeight = () => this._panelHeight;
     getContentsHeight = () => this._panelHeight - this._buttonBarHeight;
 
@@ -329,7 +349,6 @@ export class MainView extends React.Component {
             NativeWidth={returnZero}
             PanelWidth={this.getPWidth}
             PanelHeight={this.getPHeight}
-            renderDepth={0}
             focus={emptyFunction}
             parentActive={returnTrue}
             whenActiveChanged={emptyFunction}
@@ -570,6 +589,30 @@ export class MainView extends React.Component {
         }
     }
 
+    @action
+    onDown = (e: React.PointerEvent) => {
+        setupMoveUpEvents(this, e, action((e: PointerEvent, down: number[], delta: number[]) => {
+            this._propertiesWidth = this._panelWidth - Math.max(Transform.Identity().transformPoint(e.clientX, 0)[0], 0);
+            return false;
+        }), returnFalse, action(() => this._propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this._panelWidth - 50, 200) : 0), false);
+    }
+
+    @computed get propertiesView() {
+        TraceMobx();
+        return this._propertiesWidth === 0 ? (null) :
+            <div className="mainView-propertiesView" style={{
+                width: `${this.propertiesWidth()}px`,
+                overflow: this.propertiesWidth() < 15 ? "hidden" : undefined
+            }}>
+                <PropertiesView
+                    width={this._propertiesWidth}
+                    height={this._panelHeight}
+                    renderDepth={1}
+                    ScreenToLocalTransform={Transform.Identity}
+                />
+            </div>;
+    }
+
     @computed get mainContent() {
         const n = (RichTextMenu.Instance?.Pinned ? 1 : 0) + (CollectionMenu.Instance?.Pinned ? 1 : 0);
         const height = `calc(100% - ${n * Number(ANTIMODEMENU_HEIGHT.replace("px", ""))}px)`;
@@ -606,6 +649,14 @@ export class MainView extends React.Component {
                         </div>
                     </div>
                     {this.dockingContent}
+                    {this.showProperties ? (null) :
+                        <div className="mainView-propertiesDragger" title="Properties View Dragger" onPointerDown={this.onDown}
+                            style={{ right: this._propertiesWidth - 1, top: "45%" }}>
+                            <div className="mainView-propertiesDragger-icon">
+                                <FontAwesomeIcon icon={this.propertiesIcon} color="white" size="sm" /> </div>
+                        </div>
+                    }
+                    {this.propertiesWidth() < 10 ? (null) : this.propertiesView}
                 </div>
             </div>);
     }
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index 842d0320f..1b06a41fa 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -22,6 +22,7 @@ import { TemplateMenu } from "./TemplateMenu";
 import { Template, Templates } from "./Templates";
 import React = require("react");
 import { Tooltip } from '@material-ui/core';
+import { SelectionManager } from '../util/SelectionManager';
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -49,7 +50,7 @@ enum UtilityButtonState {
 }
 
 @observer
-export class PropertiesButtons extends React.Component<{ doc: Doc }, {}> {
+export class PropertiesButtons extends React.Component<{}, {}> {
     private _dragRef = React.createRef<HTMLDivElement>();
     private _pullAnimating = false;
     private _pushAnimating = false;
@@ -67,6 +68,9 @@ export class PropertiesButtons extends React.Component<{ doc: Doc }, {}> {
     public static hasPushedHack = false;
     public static hasPulledHack = false;
 
+    @observable selectedDocumentView: DocumentView | undefined = SelectionManager.LastSelection();
+    @observable selectedDoc: Doc | undefined = this.selectedDocumentView?.props.Document;
+
     public startPullOutcome = action((success: boolean) => {
         if (!this._pullAnimating) {
             this._pullAnimating = true;
@@ -108,7 +112,7 @@ export class PropertiesButtons extends React.Component<{ doc: Doc }, {}> {
 
     @computed
     get considerGoogleDocsPush() {
-        const targetDoc = this.props.doc;
+        const targetDoc = this.selectedDoc;
         const published = targetDoc && Doc.GetProto(targetDoc)[GoogleRef] !== undefined;
         const animation = this.isAnimatingPulse ? "shadow-pulse 1s linear infinite" : "none";
         return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{`${published ? "Push" : "Publish"} to Google Docs`}</div></>}>
@@ -127,7 +131,7 @@ export class PropertiesButtons extends React.Component<{ doc: Doc }, {}> {
 
     @computed
     get considerGoogleDocsPull() {
-        const targetDoc = this.props.doc;
+        const targetDoc = this.selectedDoc;
         const dataDoc = targetDoc && Doc.GetProto(targetDoc);
         const animation = this.isAnimatingFetch ? "spin 0.5s linear infinite" : "none";
 
@@ -188,7 +192,7 @@ export class PropertiesButtons extends React.Component<{ doc: Doc }, {}> {
     }
     @computed
     get pinButton() {
-        const targetDoc = this.props.doc;
+        const targetDoc = this.selectedDoc;
         const isPinned = targetDoc && Doc.isDocPinned(targetDoc);
         return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}</div></>}>
             <div className="propertiesButtons-linker"
@@ -202,15 +206,20 @@ export class PropertiesButtons extends React.Component<{ doc: Doc }, {}> {
     @computed
     get metadataButton() {
         //const view0 = this.view0;
-        return <Tooltip title={<><div className="dash-tooltip">Show metadata panel</div></>}>
-            <div className="propertiesButtons-linkFlyout">
-                <Flyout anchorPoint={anchorPoints.LEFT_TOP}
-                    content={<MetadataEntryMenu docs={[this.props.doc]} suggestWithFunction />  /* tfs: @bcz This might need to be the data document? */}>
-                    <div className={"propertiesButtons-linkButton-" + "empty"} onPointerDown={e => e.stopPropagation()} >
-                        {<FontAwesomeIcon className="documentdecorations-icon" icon="tag" size="sm" />}
-                    </div>
-                </Flyout>
-            </div></Tooltip>;
+        if (this.selectedDoc) {
+            return <Tooltip title={<><div className="dash-tooltip">Show metadata panel</div></>}>
+                <div className="propertiesButtons-linkFlyout">
+                    <Flyout anchorPoint={anchorPoints.LEFT_TOP}
+                        content={<MetadataEntryMenu docs={[this.selectedDoc]} suggestWithFunction />  /* tfs: @bcz This might need to be the data document? */}>
+                        <div className={"propertiesButtons-linkButton-" + "empty"} onPointerDown={e => e.stopPropagation()} >
+                            {<FontAwesomeIcon className="documentdecorations-icon" icon="tag" size="sm" />}
+                        </div>
+                    </Flyout>
+                </div></Tooltip>;
+        } else {
+            return null;
+        }
+
     }
 
     // @computed
@@ -267,9 +276,9 @@ export class PropertiesButtons extends React.Component<{ doc: Doc }, {}> {
     // }
 
     render() {
-        if (!this.props.doc) return (null);
+        if (!this.selectedDoc) return (null);
 
-        const isText = this.props.doc[Doc.LayoutFieldKey(this.props.doc)] instanceof RichTextField;
+        const isText = this.selectedDoc[Doc.LayoutFieldKey(this.selectedDoc)] instanceof RichTextField;
         const considerPull = isText && this.considerGoogleDocsPull;
         const considerPush = isText && this.considerGoogleDocsPush;
         return <div className="propertiesButtons">
diff --git a/src/client/views/collections/CollectionView.scss b/src/client/views/collections/CollectionView.scss
index 585f6865e..a5aef86de 100644
--- a/src/client/views/collections/CollectionView.scss
+++ b/src/client/views/collections/CollectionView.scss
@@ -25,40 +25,6 @@
         z-index: 2;
     }
 
-    .collectionView-propertiesDragger {
-        background-color: rgb(140, 139, 139);
-        height: 55px;
-        width: 15.5px;
-        position: absolute;
-        top: 55%;
-        border: 1px black solid;
-        border-radius: 0;
-        border-top-left-radius: 10px;
-        border-bottom-left-radius: 10px;
-        border-right: unset;
-        z-index: 2;
-
-        .collectionView-propertiesDragger-icon {
-            width: 10px;
-            height: 10px;
-            float: left;
-            margin-left: 3px;
-            padding-top: 19px;
-        }
-    }
-
-    .collectionView-propertiesView {
-        display: flex;
-        flex-direction: column;
-        width: 200px;
-        height: 100%;
-        position: absolute;
-        right: 0;
-        top: 0;
-        border-left: solid 1px;
-        z-index: 10;
-    }
-
     .collectionTimeView-treeView {
         display: flex;
         flex-direction: column;
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 853321d3c..19a82a113 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -49,7 +49,6 @@ import { CollectionTreeView } from "./CollectionTreeView";
 import './CollectionView.scss';
 import CollectionMenu from './CollectionMenu';
 import { SharingPermissions } from '../../util/SharingManager';
-import { PropertiesView } from './collectionFreeForm/PropertiesView';
 import { DocumentView } from '../nodes/DocumentView';
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
@@ -369,22 +368,9 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
     get _facetWidth() { return NumCast(this.props.Document._facetWidth); }
     set _facetWidth(value) { this.props.Document._facetWidth = value; }
 
-    get _propertiesWidth() { return NumCast(this.props.Document._propertiesWidth); }
-    set _propertiesWidth(value) { this.props.Document._propertiesWidth = value; }
-
-    bodyPanelWidth = () => this.props.PanelWidth() - this.propertiesWidth();
+    bodyPanelWidth = () => this.props.PanelWidth();
     facetWidth = () => Math.max(0, Math.min(this.props.PanelWidth() - 25, this._facetWidth));
 
-    propertiesWidth = () => Math.max(0, Math.min(this.props.PanelWidth() - 25, this._propertiesWidth));
-
-    @computed get propertiesIcon() {
-        if (this.propertiesWidth() < 10) {
-            return "chevron-left";
-        } else {
-            return "chevron-right";
-        }
-    }
-
     @computed get dataDoc() {
         return (this.props.DataDoc && this.props.Document.isTemplateForField ? Doc.GetProto(this.props.DataDoc) :
             this.props.Document.resolvedDataDoc ? this.props.Document : Doc.GetProto(this.props.Document)); // if the layout document has a resolvedDataDoc, then we don't want to get its parent which would be the unexpanded template
@@ -505,13 +491,6 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
         }), returnFalse, action(() => this._facetWidth = this.facetWidth() < 15 ? Math.min(this.props.PanelWidth() - 25, 200) : 0), false);
     }
 
-    onDown = (e: React.PointerEvent) => {
-        setupMoveUpEvents(this, e, action((e: PointerEvent, down: number[], delta: number[]) => {
-            this._propertiesWidth = this.props.PanelWidth() - Math.max(this.props.ScreenToLocalTransform().transformPoint(e.clientX, 0)[0], 0);
-            return false;
-        }), returnFalse, action(() => this._propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this.props.PanelWidth() - 25, 200) : 0), false);
-    }
-
     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() {
@@ -582,23 +561,6 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
             </div>;
     }
 
-    @computed get propertiesView() {
-        TraceMobx();
-        return !this._propertiesWidth || this.props.dontRegisterView ? (null) :
-            <div className="collectionView-propertiesView" style={{
-                width: `${this.propertiesWidth()}px`,
-                overflow: this.propertiesWidth() < 15 ? "hidden" : undefined
-            }}>
-                <PropertiesView dataDoc={this.dataDoc} Document={this.props.Document}
-                    docView={CollectionView as unknown as DocumentView}
-                    width={this._propertiesWidth}
-                    height={this.props.PanelHeight()}
-                    renderDepth={this.props.renderDepth}
-                    ScreenToLocalTransform={this.props.ScreenToLocalTransform}
-                />
-            </div>;
-    }
-
     childLayoutTemplate = () => this.props.childLayoutTemplate?.() || Cast(this.props.Document.childLayoutTemplate, Doc, null);
     childLayoutString = this.props.childLayoutString || StrCast(this.props.Document.childLayoutString);
 
@@ -634,15 +596,6 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
                     style={{ right: this.facetWidth() - 1, top: this.props.Document._viewType === CollectionViewType.Docking ? "25%" : "55%" }} />
             }
             {this.facetWidth() < 10 ? (null) : this.filterView} */}
-
-            {this.props.hideFilter || this.props.Document.hideFilterView || !this.props.isSelected() && !this.props.Document.forceActive ? (null) :
-                <div className="collectionView-propertiesDragger" title="Properties View Dragger" onPointerDown={this.onDown}
-                    style={{ right: this.propertiesWidth() - 1, top: this.props.Document._viewType === CollectionViewType.Docking ? "25%" : "55%" }}>
-                    <div className="collectionView-propertiesDragger-icon">
-                        <FontAwesomeIcon icon={this.propertiesIcon} color="white" size="sm" /> </div>
-                </div>
-            }
-            {this.propertiesWidth() < 10 ? (null) : this.propertiesView}
         </div>);
     }
 }
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 5242aa8fd..5aa0066d2 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -14,121 +14,162 @@ import { returnFalse, returnOne, emptyFunction, emptyPath, returnTrue, returnZer
 import { Id } from "../../../../fields/FieldSymbols";
 import { Transform } from "../../../util/Transform";
 import { PropertiesButtons } from "../../PropertiesButtons";
+import { SelectionManager } from "../../../util/SelectionManager";
 
 
 interface PropertiesViewProps {
-    dataDoc: Doc;
-    Document: Doc;
     width: number;
     height: number;
     renderDepth: number;
     ScreenToLocalTransform: () => Transform;
-    docView: DocumentView;
 }
 
 @observer
 export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     @computed get MAX_EMBED_HEIGHT() { return 200; }
+    @observable numSelected: number = SelectionManager.SelectedDocuments().length;
+    @computed get selectedDocumentView() { return SelectionManager.LastSelection(); }
+    @observable selectedDoc: Doc | undefined = this.selectedDocumentView?.props.Document;
+    @observable dataDoc: Doc | undefined = this.selectedDocumentView?.props.DataDoc ? this.selectedDocumentView.props.DataDoc : this.selectedDoc;
 
-    rtfWidth = () => Math.min(this.props.Document?.[WidthSym](), this.props.width - 20);
-    rtfHeight = () => this.rtfWidth() <= this.props.Document?.[WidthSym]() ? Math.min(this.props.Document?.[HeightSym](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT;
+    @action
+    rtfWidth = () => {
+        if (this.selectedDoc) {
+            return Math.min(this.selectedDoc?.[WidthSym](), this.props.width - 20);
+        } else {
+            return 0;
+        }
+    }
+    @action
+    rtfHeight = () => {
+        if (this.selectedDoc) {
+            return this.rtfWidth() <= this.selectedDoc?.[WidthSym]() ? Math.min(this.selectedDoc?.[HeightSym](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT;
+        } else {
+            return 0;
+        }
+    }
 
+    @action
     docWidth = () => {
-        const layoutDoc = this.props.Document;
-        const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]());
-        if (aspect) return Math.min(layoutDoc[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT / aspect, this.props.width - 20));
-        return NumCast(layoutDoc._nativeWidth) ? Math.min(layoutDoc[WidthSym](), this.props.width - 20) : this.props.width - 20;
+        if (this.selectedDoc) {
+            const layoutDoc = this.selectedDoc;
+            const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]());
+            if (aspect) return Math.min(layoutDoc[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT / aspect, this.props.width - 20));
+            return NumCast(layoutDoc._nativeWidth) ? Math.min(layoutDoc[WidthSym](), this.props.width - 20) : this.props.width - 20;
+        } else {
+            return 0;
+        }
     }
+
+    @action
     docHeight = () => {
-        const layoutDoc = this.props.Document;
-        return Math.max(70, Math.min(this.MAX_EMBED_HEIGHT, (() => {
-            const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]());
-            if (aspect) return this.docWidth() * aspect;
-            return layoutDoc._fitWidth ? (!this.props.dataDoc._nativeHeight ? NumCast(this.props.height) :
-                Math.min(this.docWidth() * NumCast(layoutDoc.scrollHeight, NumCast(layoutDoc._nativeHeight)) / NumCast(layoutDoc._nativeWidth,
-                    NumCast(this.props.height)))) :
-                NumCast(layoutDoc._height) ? NumCast(layoutDoc._height) : 50;
-        })()));
+        if (this.selectedDoc && this.dataDoc) {
+            const layoutDoc = this.selectedDoc;
+            return Math.max(70, Math.min(this.MAX_EMBED_HEIGHT, (() => {
+                const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]());
+                if (aspect) return this.docWidth() * aspect;
+                return layoutDoc._fitWidth ? (!this.dataDoc._nativeHeight ? NumCast(this.props.height) :
+                    Math.min(this.docWidth() * NumCast(layoutDoc.scrollHeight, NumCast(layoutDoc._nativeHeight)) / NumCast(layoutDoc._nativeWidth,
+                        NumCast(this.props.height)))) :
+                    NumCast(layoutDoc._height) ? NumCast(layoutDoc._height) : 50;
+            })()));
+        } else {
+            return 0;
+        }
     }
 
     @computed get expandedField() {
-        const ids: { [key: string]: string } = {};
-        const doc = this.props.dataDoc;
-        doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key));
+        if (this.dataDoc) {
+            const ids: { [key: string]: string } = {};
+            const doc = this.dataDoc;
+            doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key));
 
-        const rows: JSX.Element[] = [];
-        for (const key of Object.keys(ids).slice().sort()) {
-            const contents = doc[key];
-            let contentElement: (JSX.Element | null)[] | JSX.Element = [];
-            contentElement = <EditableView key="editableView"
-                contents={contents !== undefined ? Field.toString(contents as Field) : "null"}
-                height={13}
-                fontSize={10}
-                GetValue={() => Field.toKeyValueString(doc, key)}
-                SetValue={(value: string) => KeyValueBox.SetField(doc, key, value, true)}
-            />;
+            const rows: JSX.Element[] = [];
+            for (const key of Object.keys(ids).slice().sort()) {
+                const contents = doc[key];
+                let contentElement: (JSX.Element | null)[] | JSX.Element = [];
+                contentElement = <EditableView key="editableView"
+                    contents={contents !== undefined ? Field.toString(contents as Field) : "null"}
+                    height={13}
+                    fontSize={10}
+                    GetValue={() => Field.toKeyValueString(doc, key)}
+                    SetValue={(value: string) => KeyValueBox.SetField(doc, key, value, true)}
+                />;
 
-            rows.push(<div style={{ display: "flex", overflowY: "visible", marginBottom: "-1px" }} key={key}>
-                <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key + ":"}</span>
-                &nbsp;
-                {contentElement}
-            </div>);
+                rows.push(<div style={{ display: "flex", overflowY: "visible", marginBottom: "-1px" }} key={key}>
+                    <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key + ":"}</span>
+                    &nbsp;
+                    {contentElement}
+                </div>);
+            }
+            return rows;
         }
-        return rows;
     }
 
     @computed get layoutPreview() {
-        const layoutDoc = Doc.Layout(this.props.Document);
-        const panelHeight = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : this.docHeight;
-        const panelWidth = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : this.docWidth;
-        return <div style={{ display: "inline-block", height: panelHeight() }} key={this.props.dataDoc[Id]}>
-            <ContentFittingDocumentView
-                Document={layoutDoc}
-                DataDoc={this.props.dataDoc}
-                LibraryPath={emptyPath}
-                renderDepth={this.props.renderDepth + 1}
-                rootSelected={returnFalse}
-                treeViewDoc={undefined}
-                backgroundColor={() => "lightgrey"}
-                fitToBox={false}
-                FreezeDimensions={true}
-                NativeWidth={layoutDoc.type ===
-                    StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : returnZero}
-                NativeHeight={layoutDoc.type ===
-                    StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : returnZero}
-                PanelWidth={panelWidth}
-                PanelHeight={panelHeight}
-                focus={returnFalse}
-                ScreenToLocalTransform={this.props.ScreenToLocalTransform}
-                docFilters={returnEmptyFilter}
-                ContainingCollectionDoc={undefined}
-                ContainingCollectionView={undefined}
-                addDocument={returnFalse}
-                moveDocument={undefined}
-                removeDocument={returnFalse}
-                parentActive={() => false}
-                whenActiveChanged={emptyFunction}
-                addDocTab={returnFalse}
-                pinToPres={emptyFunction}
-                bringToFront={returnFalse}
-                ContentScaling={returnOne}
-            />
-        </div>;
+        if (this.selectedDoc) {
+            const layoutDoc = Doc.Layout(this.selectedDoc);
+            const panelHeight = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : this.docHeight;
+            const panelWidth = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : this.docWidth;
+            return <div style={{ display: "inline-block", height: panelHeight() }} key={this.selectedDoc[Id]}>
+                <ContentFittingDocumentView
+                    Document={layoutDoc}
+                    DataDoc={this.dataDoc}
+                    LibraryPath={emptyPath}
+                    renderDepth={this.props.renderDepth + 1}
+                    rootSelected={returnFalse}
+                    treeViewDoc={undefined}
+                    backgroundColor={() => "lightgrey"}
+                    fitToBox={false}
+                    FreezeDimensions={true}
+                    NativeWidth={layoutDoc.type ===
+                        StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : returnZero}
+                    NativeHeight={layoutDoc.type ===
+                        StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : returnZero}
+                    PanelWidth={panelWidth}
+                    PanelHeight={panelHeight}
+                    focus={returnFalse}
+                    ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+                    docFilters={returnEmptyFilter}
+                    ContainingCollectionDoc={undefined}
+                    ContainingCollectionView={undefined}
+                    addDocument={returnFalse}
+                    moveDocument={undefined}
+                    removeDocument={returnFalse}
+                    parentActive={() => false}
+                    whenActiveChanged={emptyFunction}
+                    addDocTab={returnFalse}
+                    pinToPres={emptyFunction}
+                    bringToFront={returnFalse}
+                    ContentScaling={returnOne}
+                />
+            </div>;
+        } else {
+            return null;
+        }
     }
 
     render() {
+
+        if (!this.selectedDocumentView || !this.selectedDoc || !this.dataDoc) {
+            return <div className="propertiesView" >
+                <div className="propertiesView-title">
+                    No Document Selected
+            </div> </div>;
+        }
+
         return <div className="propertiesView" >
             <div className="propertiesView-title">
                 Properties
             </div>
             <div className="propertiesView-name">
-                Collection
+                {this.dataDoc.title}
             </div>
             <div className="propertiesView-settings">
                 <div className="propertiesView-settings-title"> Settings</div>
                 <div className="propertiesView-settings-content">
-                    <PropertiesButtons doc={this.props.Document} />
+                    <PropertiesButtons />
                 </div>
             </div>
             <div className="propertiesView-fields">
-- 
cgit v1.2.3-70-g09d2


From 05c46464ba69e889145d8a32320cd7f130665ee1 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Thu, 23 Jul 2020 13:25:42 -0500
Subject: selection changes

---
 src/client/util/CurrentUserUtils.ts                | 47 ++++++++++++++++++++++
 src/client/util/SelectionManager.ts                | 23 +----------
 src/client/views/MainView.tsx                      | 45 ++-------------------
 .../collectionFreeForm/PropertiesView.tsx          | 12 ++++--
 4 files changed, 59 insertions(+), 68 deletions(-)

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

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 1dd25ae30..54d81a9fa 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -493,6 +493,52 @@ export class CurrentUserUtils {
         return doc.myItemCreators as Doc;
     }
 
+    static menuBtnDescriptions(): {
+        title: string, icon: string, click: string, backgroundColor?: string,
+    }[] {
+        return [
+            { title: "Workspace", icon: "desktop", click: 'this.selectPanel("workspace")' },
+            { title: "Catalog", icon: "file", click: 'this.selectPanel("catalog")' },
+            { title: "Recently Deleted", icon: "trash-alt", click: 'this.selectPanel("deleted")' },
+            { title: "Import", icon: "upload", click: 'this.selectPanel("upload")' },
+            { title: "Sharing", icon: "users", click: 'GroupManager.Instance.open()' },
+            { title: "Tools", icon: "wrench", click: 'this.selectPanel("tools")' },
+            { title: "Search", icon: "search", click: 'this.selectPanel("search")' },
+            { title: "Help", icon: "question-circle", click: 'this.selectPanel("help")' },
+            { title: "Settings", icon: "cog", click: 'SettingsManager.Instance.open()' },
+        ];
+    }
+
+    static setupMenuButtons(doc: Doc) {
+        if (doc.menuStackBtns === undefined) {
+            const buttons = CurrentUserUtils.menuBtnDescriptions();
+            const menuBtns = buttons.map(({ title, icon, click, backgroundColor }) => Docs.Create.FontIconDocument({
+                _width: 100, _height: 100,
+                icon,
+                title,
+                onClick: click ? ScriptField.MakeScript(click) : undefined,
+                backgroundColor,
+            }));
+
+            doc.menuStackBtns = new PrefetchProxy(Docs.Create.MasonryDocument(menuBtns, {
+                _xMargin: 0, _autoHeight: true, _width: 100, _columnWidth: 60, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled",
+            }));
+        }
+        return doc.menuStackBtns as Doc;
+    }
+
+    static setupMenuPanel(doc: Doc) {
+        if (doc.menuStack === undefined) {
+            const menuBtns = CurrentUserUtils.setupMenuButtons(doc);
+            doc.menuStack = new PrefetchProxy(Docs.Create.StackingDocument([menuBtns], {
+                title: "all Creators", _yMargin: 0, _autoHeight: true, _xMargin: 0,
+                _width: 100, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled",
+            })) as any as Doc;
+        }
+        return doc.menuStack;
+    }
+
+
     // Sets up mobile menu if it is undefined creates a new one, otherwise returns existing menu
     static setupActiveMobileMenu(doc: Doc) {
         if (doc.activeMobileMenu === undefined) {
@@ -894,6 +940,7 @@ export class CurrentUserUtils {
         this.setupDocTemplates(doc); // sets up the template menu of templates
         this.setupRightSidebar(doc);  // sets up the right sidebar collection for mobile upload documents and sharing
         this.setupActiveMobileMenu(doc); // sets up the current mobile menu for Dash Mobile
+        this.setupMenuPanel(doc);
         this.setupOverlays(doc);  // documents in overlay layer
         this.setupDockedButtons(doc);  // the bottom bar of font icons
         this.setupDefaultPresentation(doc); // presentation that's initially triggered
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 6fb758eac..ec875fe4b 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -13,13 +13,9 @@ export namespace SelectionManager {
         @observable IsDragging: boolean = false;
         SelectedDocuments: ObservableMap<DocumentView, boolean> = new ObservableMap();
 
-        @observable public lastSelection: DocumentView | undefined;
-
         @action
         SelectDoc(docView: DocumentView, ctrlPressed: boolean): void {
 
-            this.lastSelection = docView;
-
             // if doc is not in SelectedDocuments, add it
             if (!manager.SelectedDocuments.get(docView)) {
                 if (!ctrlPressed) {
@@ -39,14 +35,6 @@ export namespace SelectionManager {
         @action
         DeselectDoc(docView: DocumentView): void {
 
-            if (this.lastSelection === docView) {
-                const list = Array.from(manager.SelectedDocuments.keys());
-                if (list.length > 0) {
-                    this.lastSelection = list[list.length - 1];
-                } else {
-                    this.lastSelection = undefined;
-                }
-            }
             if (manager.SelectedDocuments.get(docView)) {
                 manager.SelectedDocuments.delete(docView);
                 docView.props.whenActiveChanged(false);
@@ -55,16 +43,11 @@ export namespace SelectionManager {
         }
         @action
         DeselectAll(): void {
-            this.lastSelection = undefined;
+
             Array.from(manager.SelectedDocuments.keys()).map(dv => dv.props.whenActiveChanged(false));
             manager.SelectedDocuments.clear();
             Doc.UserDoc().activeSelection = new List<Doc>([]);
         }
-
-        @action
-        getLast(): DocumentView | undefined {
-            return this.lastSelection;
-        }
     }
 
     const manager = new Manager();
@@ -76,10 +59,6 @@ export namespace SelectionManager {
         manager.SelectDoc(docView, ctrlPressed);
     }
 
-    export function LastSelection(): DocumentView | undefined {
-        return manager.getLast();
-    }
-
     // computed functions, such as used in IsSelected generate errors if they're called outside of a
     // reaction context.  Specifying the context with 'outsideReaction' allows an efficiency feature
     // to avoid unnecessary mobx invalidations when running inside a reaction.
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 9e8fa545f..8113ad698 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -456,48 +456,11 @@ export class MainView extends React.Component {
             {this.docButtons}</div>;
     }
 
-    menuBtnDescriptions(): {
-        title: string, icon: string, click: string, backgroundColor?: string,
-    }[] {
-        return [
-            { title: "Workspace", icon: "desktop", click: 'this.selectPanel("workspace")' },
-            { title: "Catalog", icon: "file", click: 'this.selectPanel("catalog")' },
-            { title: "Recently Deleted", icon: "trash-alt", click: 'this.selectPanel("deleted")' },
-            { title: "Import", icon: "upload", click: 'this.selectPanel("upload")' },
-            { title: "Sharing", icon: "users", click: 'GroupManager.Instance.open()' },
-            { title: "Tools", icon: "wrench", click: 'this.selectPanel("tools")' },
-            { title: "Search", icon: "search", click: 'this.selectPanel("search")' },
-            { title: "Help", icon: "question-circle", click: 'this.selectPanel("help")' },
-            { title: "Settings", icon: "cog", click: 'SettingsManager.Instance.open()' },
-        ];
-    }
-
-    setupMenuButtons() {
-        const buttons = this.menuBtnDescriptions();
-        const menuBtns = buttons.map(({ title, icon, click, backgroundColor }) => Docs.Create.FontIconDocument({
-            _width: 100, _height: 100,
-            icon,
-            title,
-            onClick: click ? ScriptField.MakeScript(click) : undefined,
-            backgroundColor,
-        }));
-
-        const btnStack = new PrefetchProxy(Docs.Create.MasonryDocument(menuBtns, {
-            _xMargin: 0, _autoHeight: true, _width: 100, _columnWidth: 60, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled",
-        }));
-        return btnStack as unknown as Doc;
-    }
-
-    @computed get setupMenuPanel() {
-        const menuBtns = this.setupMenuButtons();
-        const menuStack = new PrefetchProxy(Docs.Create.StackingDocument([menuBtns], {
-            title: "all Creators", _yMargin: 0, _autoHeight: true, _xMargin: 0,
-            _width: 100, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled",
-        })) as any as Doc;
+    @computed get menuPanel() {
 
         return <div className="mainView-menuPanel">
             <DocumentView
-                Document={menuStack}
+                Document={Doc.UserDoc().menuStack as Doc}
                 DataDoc={undefined}
                 LibraryPath={emptyPath}
                 addDocument={undefined}
@@ -524,8 +487,6 @@ export class MainView extends React.Component {
         </div>;
     }
 
-    @observable menuPanel: any;
-
     // @computed get menuPanel() {
     //     return <div className="mainView-menuPanel">
     //         <button className="mainView-menuPanel-button"
@@ -690,7 +651,7 @@ export class MainView extends React.Component {
                 height,
                 width: (FormatShapePane.Instance?.Pinned) ? `calc(100% - 200px)` : "100%"
             }} >
-                {this.setupMenuPanel}
+                {this.menuPanel}
                 <div style={{ display: "contents", flexDirection: "row", position: "relative" }}>
                     <div className="mainView-flyoutContainer" onPointerLeave={this.pointerLeaveDragger} style={{ width: this.flyoutWidth }}>
                         {this.flyoutWidth !== 0 ? <div className="mainView-libraryHandle"
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 5aa0066d2..11609b1c0 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -28,10 +28,14 @@ interface PropertiesViewProps {
 export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     @computed get MAX_EMBED_HEIGHT() { return 200; }
-    @observable numSelected: number = SelectionManager.SelectedDocuments().length;
-    @computed get selectedDocumentView() { return SelectionManager.LastSelection(); }
-    @observable selectedDoc: Doc | undefined = this.selectedDocumentView?.props.Document;
-    @observable dataDoc: Doc | undefined = this.selectedDocumentView?.props.DataDoc ? this.selectedDocumentView.props.DataDoc : this.selectedDoc;
+
+    @computed get selectedDocumentView() {
+        if (SelectionManger.SelectedDocuments().length) {
+            return SelectionManager.SelectedDocuments()[0];
+        } else { return undefined; }
+    }
+    @computed get selectedDoc() { return this.selectedDocumentView?.props.Document; }
+    @computed get dataDoc() { return this.selectedDocumentView?.props.DataDoc; }
 
     @action
     rtfWidth = () => {
-- 
cgit v1.2.3-70-g09d2


From feb86078832da5f7207bc5775a61d7dd93681e98 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 23 Jul 2020 14:40:57 -0400
Subject: fixes for gettin new sidebar to work

---
 src/client/views/MainView.tsx                                  |  6 +-----
 src/client/views/PropertiesButtons.tsx                         | 10 ++++++++--
 .../views/collections/collectionFreeForm/PropertiesView.tsx    | 10 +++++-----
 3 files changed, 14 insertions(+), 12 deletions(-)

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

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 8113ad698..d3bdeda9e 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -95,10 +95,6 @@ export class MainView extends React.Component {
     @observable public sidebarContent: any = this.userDoc?.["tabs-panelContainer"];
     @observable public panelContent: string = "none";
     @observable public showProperties: boolean = false;
-
-    @computed get selectedDocumentView() { return SelectionManager.LastSelection(); }
-    @observable selectedDoc: Doc | undefined = this.selectedDocumentView?.props.Document;
-    @observable selectedDataDoc: Doc | undefined = this.selectedDocumentView?.props.DataDoc ? this.selectedDocumentView.props.DataDoc : this.selectedDoc;
     public isPointerDown = false;
 
     @observable _propertiesWidth: number = 0;
@@ -359,7 +355,7 @@ export class MainView extends React.Component {
             docFilters={returnEmptyFilter}
             ContainingCollectionView={undefined}
             ContainingCollectionDoc={undefined}
-            renderDepth={1}
+            renderDepth={0}
         />;
     }
     @computed get dockingContent() {
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index 1b06a41fa..b55593b11 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -68,8 +68,14 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     public static hasPushedHack = false;
     public static hasPulledHack = false;
 
-    @observable selectedDocumentView: DocumentView | undefined = SelectionManager.LastSelection();
-    @observable selectedDoc: Doc | undefined = this.selectedDocumentView?.props.Document;
+
+    @computed get selectedDocumentView() {
+        if (SelectionManager.SelectedDocuments().length) {
+            return SelectionManager.SelectedDocuments()[0];
+        } else { return undefined; }
+    }
+    @computed get selectedDoc() { return this.selectedDocumentView?.props.Document; }
+    @computed get dataDoc() { return this.selectedDocumentView?.props.DataDoc; }
 
     public startPullOutcome = action((success: boolean) => {
         if (!this._pullAnimating) {
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 11609b1c0..1954a11bf 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -30,12 +30,12 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @computed get MAX_EMBED_HEIGHT() { return 200; }
 
     @computed get selectedDocumentView() {
-        if (SelectionManger.SelectedDocuments().length) {
+        if (SelectionManager.SelectedDocuments().length) {
             return SelectionManager.SelectedDocuments()[0];
         } else { return undefined; }
     }
-    @computed get selectedDoc() { return this.selectedDocumentView?.props.Document; }
-    @computed get dataDoc() { return this.selectedDocumentView?.props.DataDoc; }
+    @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; }
+    @computed get dataDoc() { return this.selectedDocumentView?.dataDoc; }
 
     @action
     rtfWidth = () => {
@@ -156,7 +156,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     render() {
 
-        if (!this.selectedDocumentView || !this.selectedDoc || !this.dataDoc) {
+        if (!this.selectedDoc) {
             return <div className="propertiesView" >
                 <div className="propertiesView-title">
                     No Document Selected
@@ -168,7 +168,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 Properties
             </div>
             <div className="propertiesView-name">
-                {this.dataDoc.title}
+                {this.selectedDoc.title}
             </div>
             <div className="propertiesView-settings">
                 <div className="propertiesView-settings-title"> Settings</div>
-- 
cgit v1.2.3-70-g09d2


From 433ac4ffcf2eb71557ca0baff704bd67c461cadc Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Fri, 24 Jul 2020 12:16:16 -0500
Subject: implemented  sharing UI in permissions

---
 src/client/views/MainView.tsx                      |  4 +-
 .../collectionFreeForm/PropertiesView.scss         | 79 ++++++++++++++++++++++
 .../collectionFreeForm/PropertiesView.tsx          | 76 +++++++++++++++++++++
 3 files changed, 157 insertions(+), 2 deletions(-)

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

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index beee9289e..f43eca468 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -8,7 +8,7 @@ import {
     faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faTimesCircle,
     faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faArrowsAlt, faQuoteLeft, faSortAmountDown, faAlignLeft, faAlignCenter, faAlignRight,
     faHeading, faRulerCombined, faFillDrip, faLink, faUnlink, faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSuperscript, faSubscript, faIndent, faEyeDropper,
-    faPaintRoller, faBars, faBrush, faShapes, faEllipsisH, faHandPaper, faMap, faDesktop, faTrashRestore, faUsers, faWrench, faCog
+    faPaintRoller, faBars, faBrush, faShapes, faEllipsisH, faHandPaper, faMap, faDesktop, faTrashRestore, faUsers, faWrench, faCog, faBellSlash
 } from '@fortawesome/free-solid-svg-icons';
 import { ANTIMODEMENU_HEIGHT } from './globalCssVariables.scss';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
@@ -174,7 +174,7 @@ export class MainView extends React.Component {
             faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faTrashAlt, faAngleRight, faBell,
             faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faArrowsAlt, faQuoteLeft, faSortAmountDown, faAlignLeft, faAlignCenter, faAlignRight,
             faHeading, faRulerCombined, faFillDrip, faLink, faUnlink, faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSuperscript, faSubscript, faIndent, faEyeDropper,
-            faPaintRoller, faBars, faBrush, faShapes, faEllipsisH, faHandPaper, faDesktop, faTrashRestore, faUsers, faWrench, faCog, faMap);
+            faPaintRoller, faBars, faBrush, faShapes, faEllipsisH, faHandPaper, faDesktop, faTrashRestore, faUsers, faWrench, faCog, faMap, faBellSlash);
         this.initEventListeners();
         this.initAuthenticationRouters();
     }
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index f64ef2211..e025c7e87 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -41,6 +41,85 @@
 
     }
 
+    .propertiesView-sharing {
+        border-bottom: 1px solid black;
+        padding: 8.5px;
+
+        .propertiesView-sharing-title {
+            font-size: 12.5px;
+            font-weight: bold;
+            padding-bottom: 7px;
+        }
+
+        .propertiesView-sharing-content {
+            font-size: 10px;
+            margin-left: 5px;
+        }
+    }
+
+    .notify-button {
+        padding: 2px;
+        width: 12px;
+        height: 12px;
+        background-color: black;
+        border-radius: 10px;
+        padding-left: 2px;
+        padding-right: 2px;
+        margin-top: 2px;
+        margin-right: 3px;
+
+        .notify-button-icon {
+            width: 6px;
+            height: 6.5px;
+            margin-left: .5px;
+        }
+
+        &:hover {
+            background-color: rgb(158, 158, 158);
+        }
+    }
+
+    .propertiesView-sharingTable {
+
+        border: 1px solid black;
+        padding: 5px;
+        border-radius: 6px;
+        width: 170px;
+        background-color: #ececec;
+
+        .propertiesView-sharingTable-item {
+
+            display: flex;
+            padding: 3px;
+
+            border-bottom: 0.5px solid grey;
+
+            .propertiesView-sharingTable-item-name {
+                font-weight: bold;
+                width: 80px;
+                overflow-x: hidden;
+                display: inline-block;
+            }
+
+            .propertiesView-sharingTable-item-permission {
+
+                .permissions-select {
+                    z-index: 1;
+                    //border: 0.5px solid grey;
+                    //border-radius: 4px;
+                    //outline: none;
+                    border: none;
+                    background-color: inherit;
+                    width: 75px;
+                }
+            }
+
+            &:last-child {
+                border-bottom: none;
+            }
+        }
+    }
+
     .propertiesView-fields {
         border-bottom: 1px solid black;
         padding: 8.5px;
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 1954a11bf..9af4bd276 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -15,6 +15,8 @@ import { Id } from "../../../../fields/FieldSymbols";
 import { Transform } from "../../../util/Transform";
 import { PropertiesButtons } from "../../PropertiesButtons";
 import { SelectionManager } from "../../../util/SelectionManager";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { Tooltip } from "@material-ui/core";
 
 
 interface PropertiesViewProps {
@@ -154,6 +156,74 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         }
     }
 
+    @computed get permissionsSelect() {
+        return <select className="permissions-select" onChange={emptyFunction}>
+            <option key={"Can Edit"} value={"Can Edit"}>
+                Can Edit
+                        </option>
+            <option key={"Can Add"} value={"Can Add"}>
+                Can Add
+                        </option>
+            <option key={"Can View"} value={"Can View"}>
+                Can View
+                        </option>
+            <option key={"Not Shared"} value={"Not Shared"}>
+                Not Shared
+                        </option>
+        </select>;
+    }
+
+    @computed get notifyIcon() {
+        return <Tooltip title={<><div className="dash-tooltip">{"Notify user or group of permissions change"}</div></>}>
+            <div className="notify-button">
+                <FontAwesomeIcon className="notify-button-icon" icon="bell" color="white" size="sm" />
+            </div>
+        </Tooltip>;
+    }
+
+    sharingItem(name: string, notify: boolean, editable: boolean, permission?: string) {
+        return <div className="propertiesView-sharingTable-item">
+            <div className="propertiesView-sharingTable-item-name" style={{ width: notify ? "70px" : "80px" }}> {name} </div>
+            {notify ? this.notifyIcon : null}
+            <div className="propertiesView-sharingTable-item-permission">
+                {editable ? this.permissionsSelect : permission}
+            </div>
+        </div>;
+    }
+
+    @computed get sharingTable() {
+        return <div className="propertiesView-sharingTable">
+            {this.sharingItem("Me", false, false, "Owner")}
+            {this.sharingItem("Public", false, true)}
+            {this.sharingItem("Group 1", true, true)}
+            {this.sharingItem("Group 2", true, true)}
+            {/* <div className="propertiesView-sharingTable-item">
+                <div className="propertiesView-sharingTable-item-name"> Me: </div>
+                <div className="propertiesView-sharingTable-item-permission"> Owner </div>
+            </div>
+            <div className="propertiesView-sharingTable-item">
+                <div className="propertiesView-sharingTable-item-name"> Public: </div>
+                <div className="propertiesView-sharingTable-item-permission">
+                    {this.permissionsSelect}
+                </div>
+            </div>
+            <div className="propertiesView-sharingTable-item">
+                <div className="propertiesView-sharingTable-item-name"> Group 1: </div>
+                <div> </div>
+                <div className="propertiesView-sharingTable-item-permission">
+                    {this.permissionsSelect}
+                </div>
+            </div>
+            <div className="propertiesView-sharingTable-item">
+                <div className="propertiesView-sharingTable-item-name"> Another group: </div>
+                <div> </div>
+                <div className="propertiesView-sharingTable-item-permission">
+                    {this.permissionsSelect}
+                </div>
+            </div> */}
+        </div>;
+    }
+
     render() {
 
         if (!this.selectedDoc) {
@@ -176,6 +246,12 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                     <PropertiesButtons />
                 </div>
             </div>
+            <div className="propertiesView-sharing">
+                <div className="propertiesView-sharing-title"> Sharing {"&"} Permissions</div>
+                <div className="propertiesView-sharing-content">
+                    {this.sharingTable}
+                </div>
+            </div>
             <div className="propertiesView-fields">
                 <div className="propertiesView-fields-title"> Fields</div>
                 <div className="propertiesView-fields-content"> {this.expandedField} </div>
-- 
cgit v1.2.3-70-g09d2


From 649470762c722eea1067e30d2f35aedcf84a369c Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Fri, 24 Jul 2020 13:40:24 -0500
Subject: sally UI changes

---
 src/client/views/DocumentDecorations.tsx           |  5 +--
 src/client/views/MainView.tsx                      |  4 +--
 src/client/views/PropertiesButtons.tsx             |  2 +-
 .../collectionFreeForm/PropertiesView.scss         | 13 +++++++
 .../collectionFreeForm/PropertiesView.tsx          | 42 +++++++++-------------
 src/client/views/linking/LinkMenuItem.tsx          |  2 +-
 src/client/views/nodes/DocumentView.tsx            | 12 ++++++-
 7 files changed, 47 insertions(+), 33 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index fec4ad9e0..d30adc5a2 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -1,5 +1,5 @@
 import { IconProp, library } from '@fortawesome/fontawesome-svg-core';
-import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote, faTextHeight, faArrowAltCircleDown, faArrowAltCircleUp, faCheckCircle, faCloudUploadAlt, faLink, faShare, faStopCircle, faSyncAlt, faTag, faTimes, faAngleLeft, faAngleRight, faAngleDoubleLeft, faAngleDoubleRight, faPause } from '@fortawesome/free-solid-svg-icons';
+import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote, faTextHeight, faArrowAltCircleDown, faArrowAltCircleUp, faCheckCircle, faCloudUploadAlt, faLink, faShare, faStopCircle, faSyncAlt, faTag, faTimes, faAngleLeft, faAngleRight, faAngleDoubleLeft, faAngleDoubleRight, faPause, faExternalLinkAlt } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { action, computed, observable, reaction, runInAction } from "mobx";
 import { observer } from "mobx-react";
@@ -44,6 +44,7 @@ library.add(faAngleDoubleRight);
 library.add(faAngleLeft);
 library.add(faAngleRight);
 library.add(faPause);
+library.add(faExternalLinkAlt);
 
 @observer
 export class DocumentDecorations extends React.Component<{}, { value: string }> {
@@ -617,7 +618,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                                 {"_"}
                             </div></Tooltip>}
                     <Tooltip title={<><div className="dash-tooltip">Open Document In Tab</div></>} placement="top"><div className="documentDecorations-closeButton" onPointerDown={this.onMaximizeDown}>
-                        {SelectionManager.SelectedDocuments().length === 1 ? DocumentDecorations.DocumentIcon(StrCast(seldoc.props.Document.layout, "...")) : "..."}
+                        {SelectionManager.SelectedDocuments().length === 1 ? <FontAwesomeIcon icon="external-link-alt" className="documentView-minimizedIcon" /> : "..."}
                     </div></Tooltip>
                     <div id="documentDecorations-rotation" className="documentDecorations-rotation"
                         onPointerDown={this.onRotateDown}> ⟲ </div>
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index f43eca468..4a80f57b3 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -8,7 +8,7 @@ import {
     faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faTimesCircle,
     faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faArrowsAlt, faQuoteLeft, faSortAmountDown, faAlignLeft, faAlignCenter, faAlignRight,
     faHeading, faRulerCombined, faFillDrip, faLink, faUnlink, faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSuperscript, faSubscript, faIndent, faEyeDropper,
-    faPaintRoller, faBars, faBrush, faShapes, faEllipsisH, faHandPaper, faMap, faDesktop, faTrashRestore, faUsers, faWrench, faCog, faBellSlash
+    faPaintRoller, faBars, faBrush, faShapes, faEllipsisH, faHandPaper, faMap, faDesktop, faTrashRestore, faUsers, faWrench, faCog, faBellSlash, faExpandAlt
 } from '@fortawesome/free-solid-svg-icons';
 import { ANTIMODEMENU_HEIGHT } from './globalCssVariables.scss';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
@@ -174,7 +174,7 @@ export class MainView extends React.Component {
             faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faTrashAlt, faAngleRight, faBell,
             faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faArrowsAlt, faQuoteLeft, faSortAmountDown, faAlignLeft, faAlignCenter, faAlignRight,
             faHeading, faRulerCombined, faFillDrip, faLink, faUnlink, faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSuperscript, faSubscript, faIndent, faEyeDropper,
-            faPaintRoller, faBars, faBrush, faShapes, faEllipsisH, faHandPaper, faDesktop, faTrashRestore, faUsers, faWrench, faCog, faMap, faBellSlash);
+            faPaintRoller, faBars, faBrush, faShapes, faEllipsisH, faHandPaper, faDesktop, faTrashRestore, faUsers, faWrench, faCog, faMap, faBellSlash, faExpandAlt);
         this.initEventListeners();
         this.initAuthenticationRouters();
     }
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index 8488b553f..32a98b072 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -278,7 +278,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     @computed
     get copyButton() {
         const targetDoc = this.selectedDoc;
-        return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Create a copy"}</div></>}>
+        return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Create an Alias"}</div></>}>
             <div className={"documentButtonBar-linkButton-empty"}
                 onPointerDown={this.onCopy} >
                 {<FontAwesomeIcon className="documentdecorations-icon" icon="copy" size="sm" />}
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index e025c7e87..e6bc3f15a 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -79,6 +79,17 @@
         }
     }
 
+    .expansion-button-icon {
+        width: 11px;
+        height: 11px;
+        color: black;
+        margin-left: 27px;
+
+        &:hover {
+            color: rgb(131, 131, 131);
+        }
+    }
+
     .propertiesView-sharingTable {
 
         border: 1px solid black;
@@ -103,6 +114,8 @@
 
             .propertiesView-sharingTable-item-permission {
 
+                display: flex;
+
                 .permissions-select {
                     z-index: 1;
                     //border: 0.5px solid grey;
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 9af4bd276..e911c7a9f 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -17,6 +17,7 @@ import { PropertiesButtons } from "../../PropertiesButtons";
 import { SelectionManager } from "../../../util/SelectionManager";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { Tooltip } from "@material-ui/core";
+import SharingManager from "../../../util/SharingManager";
 
 
 interface PropertiesViewProps {
@@ -174,19 +175,32 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
     @computed get notifyIcon() {
-        return <Tooltip title={<><div className="dash-tooltip">{"Notify user or group of permissions change"}</div></>}>
+        return <Tooltip title={<><div className="dash-tooltip">{"Notify group of permissions change"}</div></>}>
             <div className="notify-button">
                 <FontAwesomeIcon className="notify-button-icon" icon="bell" color="white" size="sm" />
             </div>
         </Tooltip>;
     }
 
+    @computed get expansionIcon() {
+        return <Tooltip title={<><div className="dash-tooltip">{"Show more permissions"}</div></>}>
+            <div className="expansion-button" onPointerDown={() => {
+                if (this.selectedDocumentView) {
+                    SharingManager.Instance.open(this.selectedDocumentView);
+                }
+            }}>
+                <FontAwesomeIcon className="expansion-button-icon" icon="ellipsis-h" color="black" size="sm" />
+            </div>
+        </Tooltip>;
+    }
+
     sharingItem(name: string, notify: boolean, editable: boolean, permission?: string) {
         return <div className="propertiesView-sharingTable-item">
             <div className="propertiesView-sharingTable-item-name" style={{ width: notify ? "70px" : "80px" }}> {name} </div>
             {notify ? this.notifyIcon : null}
             <div className="propertiesView-sharingTable-item-permission">
                 {editable ? this.permissionsSelect : permission}
+                {permission === "Owner" ? this.expansionIcon : null}
             </div>
         </div>;
     }
@@ -197,30 +211,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
             {this.sharingItem("Public", false, true)}
             {this.sharingItem("Group 1", true, true)}
             {this.sharingItem("Group 2", true, true)}
-            {/* <div className="propertiesView-sharingTable-item">
-                <div className="propertiesView-sharingTable-item-name"> Me: </div>
-                <div className="propertiesView-sharingTable-item-permission"> Owner </div>
-            </div>
-            <div className="propertiesView-sharingTable-item">
-                <div className="propertiesView-sharingTable-item-name"> Public: </div>
-                <div className="propertiesView-sharingTable-item-permission">
-                    {this.permissionsSelect}
-                </div>
-            </div>
-            <div className="propertiesView-sharingTable-item">
-                <div className="propertiesView-sharingTable-item-name"> Group 1: </div>
-                <div> </div>
-                <div className="propertiesView-sharingTable-item-permission">
-                    {this.permissionsSelect}
-                </div>
-            </div>
-            <div className="propertiesView-sharingTable-item">
-                <div className="propertiesView-sharingTable-item-name"> Another group: </div>
-                <div> </div>
-                <div className="propertiesView-sharingTable-item-permission">
-                    {this.permissionsSelect}
-                </div>
-            </div> */}
         </div>;
     }
 
@@ -241,7 +231,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 {this.selectedDoc.title}
             </div>
             <div className="propertiesView-settings">
-                <div className="propertiesView-settings-title"> Settings</div>
+                <div className="propertiesView-settings-title"> Document Actions </div>
                 <div className="propertiesView-settings-content">
                     <PropertiesButtons />
                 </div>
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index d1c839c3b..8084d96ae 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -182,7 +182,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
         switch (this.props.destinationDoc.type) {
             case DocumentType.IMG: destinationIcon = "image"; break;
             case DocumentType.COMPARISON: destinationIcon = "columns"; break;
-            case DocumentType.RTF: destinationIcon = "font"; break;
+            case DocumentType.RTF: destinationIcon = "sticky-note"; break;
             case DocumentType.COL: destinationIcon = "folder"; break;
             case DocumentType.WEB: destinationIcon = "globe-asia"; break;
             case DocumentType.SCREENSHOT: destinationIcon = "photo-video"; break;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 30582a287..ed3a9a4f3 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -726,6 +726,14 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         });
     }
 
+    @action
+    onCopy = () => {
+        const copy = Doc.MakeCopy(this.props.Document, true);
+        copy.x = NumCast(this.props.Document.x) + NumCast(this.props.Document._width);
+        copy.y = NumCast(this.props.Document.y) + 30;
+        this.props.addDocument?.(copy);
+    }
+
     @action
     onContextMenu = async (e: React.MouseEvent | Touch): Promise<void> => {
         // the touch onContextMenu is button 0, the pointer onContextMenu is button 2
@@ -787,6 +795,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
         const more = cm.findByDescription("More...");
         const moreItems = more && "subitems" in more ? more.subitems : [];
+        moreItems.push({ description: "Share", event: () => SharingManager.Instance.open(this), icon: "users" });
+        moreItems.push({ description: "Create an Alias", event: () => this.onCopy(), icon: "copy" });
         moreItems.push({
             description: "Download document", icon: "download", event: async () => {
                 Doc.Zip(this.props.Document);
@@ -809,7 +819,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "fingerprint" });
         }
         GetEffectiveAcl(this.props.Document) === AclEdit && moreItems.push({ description: "Delete", event: this.deleteClicked, icon: "trash" });
-        //moreItems.push({ description: "Share", event: () => SharingManager.Instance.open(this), icon: "external-link-alt" });
+
         !more && cm.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" });
         cm.moveAfter(cm.findByDescription("More...")!, cm.findByDescription("OnClick...")!);
 
-- 
cgit v1.2.3-70-g09d2


From 229e8ba914943da0d11dff00d14a8adae950d853 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Sat, 25 Jul 2020 10:27:27 -0500
Subject: exit button for properties

---
 src/client/views/MainView.tsx                      |  1 +
 .../collectionFreeForm/PropertiesView.scss         | 23 ++++++++++++++++++++--
 .../collectionFreeForm/PropertiesView.tsx          |  6 +++++-
 src/client/views/nodes/DocumentLinksButton.tsx     |  5 ++++-
 4 files changed, 31 insertions(+), 4 deletions(-)

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

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index c08717947..734b45dd0 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -621,6 +621,7 @@ export class MainView extends React.Component {
                 height={this._panelHeight}
                 renderDepth={1}
                 ScreenToLocalTransform={Transform.Identity}
+                onDown={this.onDown}
             />
         </div>;
     }
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index b40a08086..7b8f116b7 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -10,10 +10,29 @@
     .propertiesView-title {
         background-color: rgb(159, 159, 159);
         text-align: center;
-        font-size: 18px;
-        font-weight: bold;
         padding-top: 12px;
         padding-bottom: 12px;
+        display: flex;
+
+        .propertiesView-title-name {
+            font-size: 18px;
+            font-weight: bold;
+            padding-left: 45px;
+        }
+
+        .propertiesView-title-icon {
+            width: 20px;
+            height: 20px;
+            padding-left: 32px;
+            margin-top: -5px;
+
+            &:hover {
+                color: grey;
+                cursor: pointer;
+            }
+
+        }
+
     }
 
     .propertiesView-name {
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index e911c7a9f..a75ad13e5 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -25,6 +25,7 @@ interface PropertiesViewProps {
     height: number;
     renderDepth: number;
     ScreenToLocalTransform: () => Transform;
+    onDown: (event: any) => void;
 }
 
 @observer
@@ -225,7 +226,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
         return <div className="propertiesView" >
             <div className="propertiesView-title">
-                Properties
+                <div className="propertiesView-title-name">Properties </div>
+                <div className="propertiesView-title-icon" onPointerDown={this.props.onDown}>
+                    <FontAwesomeIcon icon="times" color="black" size="sm" />
+                </div>
             </div>
             <div className="propertiesView-name">
                 {this.selectedDoc.title}
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index b17accfd6..fa7fe64f3 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -194,8 +194,11 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
             // }))} 
             >
 
+                {/* {this.props.InMenu ? this.props.StartLink ? <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" /> :
+                    <FontAwesomeIcon className="documentdecorations-icon" icon="hand-paper" size="sm" /> : links.length} */}
+
                 {this.props.InMenu ? this.props.StartLink ? <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" /> :
-                    <FontAwesomeIcon className="documentdecorations-icon" icon="hand-paper" size="sm" /> : links.length}
+                    link : links.length}
 
             </div>
             {DocumentLinksButton.StartLink && this.props.InMenu && !!!this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View ? <div className={"documentLinksButton-endLink"}
-- 
cgit v1.2.3-70-g09d2


From e93058822d2b997b48fb711f49bb14357a61143c Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Sun, 26 Jul 2020 22:54:10 -0500
Subject: layout check in properties, rich text menu to top

---
 src/client/views/MainView.tsx                      |  4 +-
 src/client/views/PropertiesButtons.scss            |  9 ++
 src/client/views/PropertiesButtons.tsx             | 99 ++++++++++++++--------
 src/client/views/collections/CollectionMenu.tsx    | 44 +++++++---
 .../collectionFreeForm/PropertiesView.scss         | 21 ++++-
 .../collectionFreeForm/PropertiesView.tsx          | 31 ++++++-
 src/client/views/nodes/DocumentView.tsx            | 13 +++
 .../views/nodes/formattedText/RichTextMenu.tsx     | 47 +++++-----
 8 files changed, 192 insertions(+), 76 deletions(-)

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

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 4f85ef333..153df7d9d 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -628,7 +628,7 @@ export class MainView extends React.Component {
     }
 
     @computed get mainContent() {
-        const n = (RichTextMenu.Instance?.Pinned ? 1 : 0) + (CollectionMenu.Instance?.Pinned ? 1 : 0);
+        const n = (RichTextMenu.Instance?.Pinned ? 0 : 0) + (CollectionMenu.Instance?.Pinned ? 1 : 0);
         const height = `calc(100% - ${n * Number(ANTIMODEMENU_HEIGHT.replace("px", ""))}px)`;
 
         const rightFlyout = this.selectedDocumentView ? this._propertiesWidth - 1 : this.propertiesWidth() > 10 ? 151.5 : 0;
@@ -799,7 +799,7 @@ export class MainView extends React.Component {
             {/* {this.search} */}
             <CollectionMenu />
             <FormatShapePane />
-            <RichTextMenu key="rich" />
+            {/* <RichTextMenu key="rich" /> */}
             {LinkDescriptionPopup.descriptionPopup ? <LinkDescriptionPopup /> : null}
             {DocumentLinksButton.EditLink ? <LinkMenu location={DocumentLinksButton.EditLinkLoc} docView={DocumentLinksButton.EditLink} addDocTab={DocumentLinksButton.EditLink.props.addDocTab} changeFlyout={emptyFunction} /> : (null)}
             {LinkDocPreview.LinkInfo ? <LinkDocPreview location={LinkDocPreview.LinkInfo.Location} backgroundColor={this.defaultBackgroundColors}
diff --git a/src/client/views/PropertiesButtons.scss b/src/client/views/PropertiesButtons.scss
index 305688bdb..c3fea5e29 100644
--- a/src/client/views/PropertiesButtons.scss
+++ b/src/client/views/PropertiesButtons.scss
@@ -53,6 +53,15 @@ $linkGap : 3px;
     overflow-x: visible;
 }
 
+.onClickFlyout-editScript {
+    text-align: center;
+    border: 0.5px solid grey;
+    background-color: rgb(230, 230, 230);
+    border-radius: 9px;
+    padding: 4px;
+}
+
+
 .propertiesButtons-button {
     pointer-events: auto;
     padding-right: 5px;
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index a512b3232..f1cb24425 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -26,6 +26,7 @@ import { SelectionManager } from '../util/SelectionManager';
 import SharingManager from '../util/SharingManager';
 import { GooglePhotos } from '../apis/google_docs/GooglePhotosClientUtils';
 import { ImageField } from '../../fields/URLField';
+import { undoBatch, UndoManager } from '../util/UndoManager';
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -80,6 +81,8 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; }
     @computed get dataDoc() { return this.selectedDocumentView?.dataDoc; }
 
+    @observable public onClick = this.selectedDoc?.onClickBehavior ? this.selectedDoc?.onClickBehavior : "nothing";
+
     public startPullOutcome = action((success: boolean) => {
         if (!this._pullAnimating) {
             this._pullAnimating = true;
@@ -373,54 +376,80 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         }
     }
 
+    @action
+    handleOptionChange = (e: any) => {
+        const value = e.target.value;
+        this.onClick = e.target.value;
+        if (value === "nothing") {
+            this.selectedDocumentView?.noOnClick;
+        } else if (value === "enterPortal") {
+            //this.selectedDocumentView?.noOnClick;
+            this.selectedDocumentView?.makeIntoPortal;
+        } else if (value === "toggleDetail") {
+            //this.selectedDocumentView?.noOnClick;
+            this.selectedDocumentView?.toggleDetail;
+        } else if (value === "linkInPlace") {
+            //this.selectedDocumentView?.noOnClick;
+            this.selectedDocumentView?.toggleFollowInPlace;
+        } else if (value === "linkOnRight") {
+            //this.selectedDocumentView?.noOnClick;
+            this.selectedDocumentView?.toggleFollowOnRight;
+        }
+    }
+
+    @undoBatch @action
+    editOnClickScript = () => {
+        if (this.selectedDoc) {
+            DocUtils.makeCustomViewClicked(this.selectedDoc, undefined, "onClick");
+        }
+    }
+
     @computed
     get onClickFlyout() {
         return <div><form>
             <div className="radio">
                 <label>
-                    <input type="radio" value="option1" checked={true} />
-                Enter Portal
-            </label>
+                    <input type="radio" value="nothing"
+                        checked={this.onClick === 'nothing'}
+                        onChange={this.handleOptionChange} />
+                    Select Document
+                </label>
             </div>
             <div className="radio">
                 <label>
-                    <input type="radio" value="option2" />
-                Toggle Detail
-            </label>
+                    <input type="radio" value="enterPortal"
+                        checked={this.onClick === 'enterPortal'}
+                        onChange={this.handleOptionChange} />
+                    Enter Portal
+                </label>
             </div>
             <div className="radio">
                 <label>
-                    <input type="radio" value="option3" />
-                Do Nothing
-            </label>
+                    <input type="radio" value="toggleDetail"
+                        checked={this.onClick === 'toggleDetail'}
+                        onChange={this.handleOptionChange} />
+                    Toggle Detail
+                </label>
             </div>
             <div className="radio">
                 <label>
-                    <input type="radio" value="option3" />
-                Follow Link in Place
-            </label>
+                    <input type="radio" value="linkInPlace"
+                        checked={this.onClick === 'linkInPlace'}
+                        onChange={this.handleOptionChange} />
+                    Follow Link
+                </label>
             </div>
             <div className="radio">
                 <label>
-                    <input type="radio" value="option3" />
-                Follow Link on Right
-            </label>
+                    <input type="radio" value="linkOnRight"
+                        checked={this.onClick === 'linkOnRight'}
+                        onChange={this.handleOptionChange} />
+                    Open Link on Right
+                </label>
             </div>
-            <div className="radio">
-                <label>
-                    <input type="radio" value="option3" />
-                Edit onClick Script
-            </label>
-            </div>
-        </form> </div>;
-
-        // onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" });
-        // onClicks.push({ description: "Toggle Detail", event: () => this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`), icon: "window-restore" });
-        // onClicks.push({ description: this.Document.ignoreClick ? "Select" : "Do Nothing", event: () => this.Document.ignoreClick = !this.Document.ignoreClick, icon: this.Document.ignoreClick ? "unlock" : "lock" });
-        // onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link in Place", event: this.toggleFollowInPlace, icon: "concierge-bell" });
-        // onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link on Right", event: this.toggleFollowOnRight, icon: "concierge-bell" });
-        // onClicks.push({ description: this.Document.isLinkButton || this.onClickHandler ? "Remove Click Behavior" : "Follow Link", event: this.toggleLinkButtonBehavior, icon: "concierge-bell" });
-        // onClicks.push({ description: "Edit onClick Script", event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"), icon: "edit" });
+        </form>
+            <div onPointerDown={this.editOnClickScript} className="onClickFlyout-editScript"> Edit onClick Script</div>
+        </div>;
     }
 
     @computed
@@ -452,9 +481,9 @@ export class PropertiesButtons extends React.Component<{}, {}> {
             <div className="propertiesButtons-button">
                 {this.templateButton}
             </div>
-            <div className="propertiesButtons-button">
+            {/* <div className="propertiesButtons-button">
                 {this.metadataButton}
-            </div>
+            </div> */}
             <div className="propertiesButtons-button">
                 {this.pinButton}
             </div>
@@ -470,14 +499,14 @@ export class PropertiesButtons extends React.Component<{}, {}> {
             <div className="propertiesButtons-button">
                 {this.deleteButton}
             </div>
+            <div className="propertiesButtons-button">
+                {this.onClickButton}
+            </div>
         </div>
             <div className="propertiesButtons">
                 <div className="propertiesButtons-button">
                     {this.sharingButton}
                 </div>
-                <div className="propertiesButtons-button">
-                    {this.onClickButton}
-                </div>
                 <div className="propertiesButtons-button" style={{ display: !considerPush ? "none" : "" }}>
                     {this.considerGoogleDocsPush}
                 </div>
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 24be69050..5a7c98f46 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -25,6 +25,8 @@ import { SelectionManager } from "../../util/SelectionManager";
 import { DocumentView } from "../nodes/DocumentView";
 import { ColorState } from "react-color";
 import { ObjectField } from "../../../fields/ObjectField";
+import RichTextMenu from "../nodes/formattedText/RichTextMenu";
+import { RichTextField } from "../../../fields/RichTextField";
 
 @observer
 export default class CollectionMenu extends AntimodeMenu {
@@ -300,6 +302,20 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
     @computed get childDocs() {
         return DocListCast(this.dataField);
     }
+
+    @computed get selectedDocumentView() {
+        if (SelectionManager.SelectedDocuments().length) {
+            return SelectionManager.SelectedDocuments()[0];
+        } else { return undefined; }
+    }
+    @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; }
+    @computed get isText() {
+        if (this.selectedDoc) {
+            return this.selectedDoc[Doc.LayoutFieldKey(this.selectedDoc)] instanceof RichTextField;
+        }
+        else return false;
+    }
+
     @undoBatch
     @action
     nextKeyframe = (): void => {
@@ -469,25 +485,27 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
     render() {
         return this.Document.isAnnotationOverlay ? (null) :
             <div className="collectionFreeFormMenu-cont">
-                <div key="map" title="mini map" className="backKeyframe" onClick={this.miniMap}>
+                {!!!this.isText ? <div key="map" title="mini map" className="backKeyframe" onClick={this.miniMap}>
                     <FontAwesomeIcon icon={"map"} size={"lg"} />
-                </div>
-                <div key="back" title="back frame" className="backKeyframe" onClick={this.prevKeyframe}>
+                </div> : null}
+                {!!!this.isText ? <div key="back" title="back frame" className="backKeyframe" onClick={this.prevKeyframe}>
                     <FontAwesomeIcon icon={"caret-left"} size={"lg"} />
-                </div>
-                <div key="num" title="toggle view all" className="numKeyframe" style={{ backgroundColor: this.Document.editing ? "#759c75" : "#c56565" }}
+                </div> : null}
+                {!!!this.isText ? <div key="num" title="toggle view all" className="numKeyframe" style={{ backgroundColor: this.Document.editing ? "#759c75" : "#c56565" }}
                     onClick={action(() => this.Document.editing = !this.Document.editing)} >
                     {NumCast(this.Document.currentFrame)}
-                </div>
-                <div key="fwd" title="forward frame" className="fwdKeyframe" onClick={this.nextKeyframe}>
+                </div> : null}
+                {!!!this.isText ? <div key="fwd" title="forward frame" className="fwdKeyframe" onClick={this.nextKeyframe}>
                     <FontAwesomeIcon icon={"caret-right"} size={"lg"} />
-                </div>
+                </div> : null}
+
+                {!!!this.isText ? this.widthPicker : null}
+                {!!!this.isText ? this.colorPicker : null}
+                {!!!this.isText ? this.fillPicker : null}
+                {!!!this.isText ? this.drawButtons : null}
+                {!!!this.isText ? this.formatPane : null}
+                {this.isText ? <RichTextMenu key="rich" /> : null}
 
-                {this.widthPicker}
-                {this.colorPicker}
-                {this.fillPicker}
-                {this.drawButtons}
-                {this.formatPane}
             </div>;
     }
 }
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index 99db0022e..8cc591875 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -164,9 +164,26 @@
         padding: 8.5px;
 
         .propertiesView-fields-title {
-            font-size: 12.5px;
-            font-weight: bold;
             padding-bottom: 7px;
+            display: flex;
+
+            .propertiesView-fields-title-name {
+                font-size: 12.5px;
+                font-weight: bold;
+            }
+
+            .propertiesView-fields-title-checkbox {
+                float: right;
+                height: 20px;
+                margin-top: -13px;
+                margin-left: 115px;
+
+                .propertiesView-fields-title-checkbox-text {
+                    font-size: 7px;
+                    margin-top: -10px;
+                    margin-left: 6px;
+                }
+            }
         }
 
         .propertiesView-fields-content {
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index a75ad13e5..3b8d782aa 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -16,7 +16,7 @@ import { Transform } from "../../../util/Transform";
 import { PropertiesButtons } from "../../PropertiesButtons";
 import { SelectionManager } from "../../../util/SelectionManager";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { Tooltip } from "@material-ui/core";
+import { Tooltip, Checkbox } from "@material-ui/core";
 import SharingManager from "../../../util/SharingManager";
 
 
@@ -41,6 +41,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; }
     @computed get dataDoc() { return this.selectedDocumentView?.dataDoc; }
 
+    @observable layoutFields: boolean = false;
+
     @action
     rtfWidth = () => {
         if (this.selectedDoc) {
@@ -88,9 +90,9 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
     @computed get expandedField() {
-        if (this.dataDoc) {
+        if (this.dataDoc && this.selectedDoc) {
             const ids: { [key: string]: string } = {};
-            const doc = this.dataDoc;
+            const doc = this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc;
             doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key));
 
             const rows: JSX.Element[] = [];
@@ -215,6 +217,19 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         </div>;
     }
 
+    @computed get fieldsCheckbox() {
+        return <Checkbox
+            color="primary"
+            onChange={this.toggleCheckbox}
+            checked={this.layoutFields}
+        />;
+    }
+
+    @action
+    toggleCheckbox = () => {
+        this.layoutFields = !this.layoutFields;
+    }
+
     render() {
 
         if (!this.selectedDoc) {
@@ -247,7 +262,15 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 </div>
             </div>
             <div className="propertiesView-fields">
-                <div className="propertiesView-fields-title"> Fields</div>
+                <div className="propertiesView-fields-title">
+                    <div className="propertiesView-fields-title-name">
+                        Fields
+                    </div>
+                    <div className="propertiesView-fields-title-checkbox">
+                        {this.fieldsCheckbox}
+                        <div className="propertiesView-fields-title-checkbox-text">Layout</div>
+                    </div>
+                </div>
                 <div className="propertiesView-fields-content"> {this.expandedField} </div>
             </div>
             <div className="propertiesView-layout">
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 6aceec90e..884104f62 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -622,6 +622,18 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         }
     }
 
+
+    @undoBatch
+    noOnClick = (): void => {
+        this.Document.ignoreClick = false;
+        this.Document.isLinkButton = false;
+    }
+
+    @undoBatch
+    toggleDetail = (): void => {
+        this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`);
+    }
+
     @undoBatch
     @action
     drop = async (e: Event, de: DragManager.DropEvent) => {
@@ -673,6 +685,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     @undoBatch
     @action
     makeIntoPortal = async () => {
+        console.log("into portal");
         const portalLink = DocListCast(this.Document.links).find(d => d.anchor1 === this.props.Document);
         if (!portalLink) {
             const portal = Docs.Create.FreeformDocument([], { _width: NumCast(this.layoutDoc._width) + 10, _height: NumCast(this.layoutDoc._height), title: StrCast(this.props.Document.title) + ".portal" });
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index 47a4911b8..98c786566 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -77,7 +77,8 @@ export default class RichTextMenu extends AntimodeMenu {
         super(props);
         RichTextMenu.Instance = this;
         this._canFade = false;
-        this.Pinned = BoolCast(Doc.UserDoc()["menuRichText-pinned"]);
+        //this.Pinned = BoolCast(Doc.UserDoc()["menuRichText-pinned"]);
+        this.Pinned = true;
 
         this.fontSizeOptions = [
             { mark: schema.marks.pFontSize.create({ fontSize: 7 }), title: "Set font size", label: "7pt", command: this.changeFontSize },
@@ -918,28 +919,34 @@ export default class RichTextMenu extends AntimodeMenu {
     render() {
         TraceMobx();
         const row1 = <div className="antimodeMenu-row" key="row 1" style={{ display: this.collapsed ? "none" : undefined }}>{[
-            !this.collapsed ? this.getDragger() : (null),
-            !this.Pinned ? (null) : <div key="frag1"> {[
-                this.createButton("bold", "Bold", this.boldActive, toggleMark(schema.marks.strong)),
-                this.createButton("italic", "Italic", this.italicsActive, toggleMark(schema.marks.em)),
-                this.createButton("underline", "Underline", this.underlineActive, toggleMark(schema.marks.underline)),
-                this.createButton("strikethrough", "Strikethrough", this.strikethroughActive, toggleMark(schema.marks.strikethrough)),
-                this.createButton("superscript", "Superscript", this.superscriptActive, toggleMark(schema.marks.superscript)),
-                this.createButton("subscript", "Subscript", this.subscriptActive, toggleMark(schema.marks.subscript)),
-                <div className="richTextMenu-divider" key="divider" />
-            ]}</div>,
+            //!this.collapsed ? this.getDragger() : (null),
+            // !this.Pinned ? (null) : <div key="frag1"> {[
+            //     this.createButton("bold", "Bold", this.boldActive, toggleMark(schema.marks.strong)),
+            //     this.createButton("italic", "Italic", this.italicsActive, toggleMark(schema.marks.em)),
+            //     this.createButton("underline", "Underline", this.underlineActive, toggleMark(schema.marks.underline)),
+            //     this.createButton("strikethrough", "Strikethrough", this.strikethroughActive, toggleMark(schema.marks.strikethrough)),
+            //     this.createButton("superscript", "Superscript", this.superscriptActive, toggleMark(schema.marks.superscript)),
+            //     this.createButton("subscript", "Subscript", this.subscriptActive, toggleMark(schema.marks.subscript)),
+            //     <div className="richTextMenu-divider" key="divider" />
+            // ]}</div>,
+            this.createButton("bold", "Bold", this.boldActive, toggleMark(schema.marks.strong)),
+            this.createButton("italic", "Italic", this.italicsActive, toggleMark(schema.marks.em)),
+            this.createButton("underline", "Underline", this.underlineActive, toggleMark(schema.marks.underline)),
+            this.createButton("strikethrough", "Strikethrough", this.strikethroughActive, toggleMark(schema.marks.strikethrough)),
+            this.createButton("superscript", "Superscript", this.superscriptActive, toggleMark(schema.marks.superscript)),
+            this.createButton("subscript", "Subscript", this.subscriptActive, toggleMark(schema.marks.subscript)),
             this.createColorButton(),
             this.createHighlighterButton(),
-            this.createLinkButton(),
-            this.createBrushButton(),
+            //this.createLinkButton(),
+            //this.createBrushButton(),
             <div className="richTextMenu-divider" key="divider 2" />,
             this.createButton("align-left", "Align Left", this.activeAlignment === "left", this.alignLeft),
             this.createButton("align-center", "Align Center", this.activeAlignment === "center", this.alignCenter),
             this.createButton("align-right", "Align Right", this.activeAlignment === "right", this.alignRight),
             this.createButton("indent", "Inset More", undefined, this.insetParagraph),
             this.createButton("outdent", "Inset Less", undefined, this.outsetParagraph),
-            this.createButton("hand-point-left", "Hanging Indent", undefined, this.hangingIndentParagraph),
-            this.createButton("hand-point-right", "Indent", undefined, this.indentParagraph),
+            //this.createButton("hand-point-left", "Hanging Indent", undefined, this.hangingIndentParagraph),
+            //this.createButton("hand-point-right", "Indent", undefined, this.indentParagraph),
         ]}</div>;
 
         const row2 = <div className="antimodeMenu-row row-2" key="row2">
@@ -950,21 +957,21 @@ export default class RichTextMenu extends AntimodeMenu {
                 this.createMarksDropdown(this.activeFontFamily, this.fontFamilyOptions, "font family", action((val: string) => this.activeFontFamily = val)),
                 <div className="richTextMenu-divider" key="divider 4" />,
                 this.createNodesDropdown(this.activeListType, this.listTypeOptions, "list type", action((val: string) => this.activeListType = val)),
-                this.createButton("sort-amount-down", "Summarize", undefined, this.insertSummarizer),
+                //this.createButton("sort-amount-down", "Summarize", undefined, this.insertSummarizer),
                 this.createButton("quote-left", "Blockquote", undefined, this.insertBlockquote),
                 this.createButton("minus", "Horizontal Rule", undefined, this.insertHorizontalRule),
                 <div className="richTextMenu-divider" key="divider 5" />,]}
             </div>
-            <div key="collapser">
-                {/* <div key="collapser">
+            {/* <div key="collapser">
+                {<div key="collapser">
                     <button className="antimodeMenu-button" key="collapse menu" title="Collapse menu" onClick={this.toggleCollapse} style={{ backgroundColor: this.collapsed ? "#121212" : "", width: 25 }}>
                         <FontAwesomeIcon icon="chevron-left" size="lg" style={{ transitionProperty: "transform", transitionDuration: "0.3s", transform: `rotate(${this.collapsed ? 180 : 0}deg)` }} />
                     </button>
-                </div> */}
+                </div> }
                 <button className="antimodeMenu-button" key="pin menu" title="Pin menu" onClick={this.toggleMenuPin} style={{ backgroundColor: this.Pinned ? "#121212" : "", display: this.collapsed ? "none" : undefined }}>
                     <FontAwesomeIcon icon="thumbtack" size="lg" style={{ transitionProperty: "transform", transitionDuration: "0.1s", transform: `rotate(${this.Pinned ? 45 : 0}deg)` }} />
                 </button>
-            </div>
+            </div> */}
         </div>;
 
         return (
-- 
cgit v1.2.3-70-g09d2


From d4f416ef5715c8f03132244831094f8485c5e6bf Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Mon, 27 Jul 2020 16:57:51 -0500
Subject: onClick functionality and pin change

---
 src/client/views/PropertiesButtons.tsx             | 44 +++++++++++-----------
 .../collectionFreeForm/PropertiesView.scss         | 10 +++++
 .../collectionFreeForm/PropertiesView.tsx          | 13 +++++++
 3 files changed, 45 insertions(+), 22 deletions(-)

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

diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index 1f13d0b07..336cd6ff9 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -206,7 +206,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         const isPinned = targetDoc && Doc.isDocPinned(targetDoc);
         return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}</div></>}>
             <div className="propertiesButtons-linker"
-                style={{ backgroundColor: isPinned ? "black" : "white", color: isPinned ? "white" : "black" }}
+                style={{ backgroundColor: isPinned ? "white" : "#121721", color: isPinned ? "black" : "white" }}
                 onClick={e => DockedFrameRenderer.PinDoc(targetDoc, isPinned)}>
                 <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin"
                 />
@@ -261,10 +261,10 @@ export class PropertiesButtons extends React.Component<{}, {}> {
             templates.set(template, views.reduce((checked, doc) => checked || doc?.props.Document["_show" + template.Name] ? true : false, false as boolean)));
         return !docView ? (null) :
             <Tooltip title={<><div className="dash-tooltip">Tap: Customize layout.  Drag: Create alias</div></>}>
-                <div className="documentButtonBar-linkFlyout" ref={this._dragRef}>
+                <div className="propertiesButtons-linkFlyout" ref={this._dragRef}>
                     <Flyout anchorPoint={anchorPoints.LEFT_TOP} onOpen={action(() => this._aliasDown = true)} onClose={action(() => this._aliasDown = false)}
                         content={!this._aliasDown ? (null) : <TemplateMenu docViews={views.filter(v => v).map(v => v as DocumentView)} templates={templates} />}>
-                        <div className={"documentButtonBar-linkButton-empty"} ref={this._dragRef} onPointerDown={this.onAliasButtonDown} >
+                        <div className={"propertiesButtons-linkButton-empty"} ref={this._dragRef} onPointerDown={this.onAliasButtonDown} >
                             {<FontAwesomeIcon className="documentdecorations-icon" icon="edit" size="sm" />}
                         </div>
                     </Flyout>
@@ -284,7 +284,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     get copyButton() {
         const targetDoc = this.selectedDoc;
         return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Create an Alias"}</div></>}>
-            <div className={"documentButtonBar-linkButton-empty"}
+            <div className={"propertiesButtons-linkButton-empty"}
                 onPointerDown={this.onCopy} >
                 {<FontAwesomeIcon className="documentdecorations-icon" icon="copy" size="sm" />}
             </div>
@@ -302,7 +302,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         return !targetDoc ? (null) : <Tooltip
             title={<><div className="dash-tooltip">{this.selectedDoc?.lockedPosition ?
                 "Unlock Position" : "Lock Position"}</div></>}>
-            <div className={"documentButtonBar-linkButton-empty"}
+            <div className={"propertiesButtons-linkButton-empty"}
                 onPointerDown={this.onLock} >
                 {<FontAwesomeIcon className="documentdecorations-icon"
                     icon={BoolCast(this.selectedDoc?.lockedPosition) ? "unlock" : "lock"} size="sm" />}
@@ -315,13 +315,13 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         const targetDoc = this.selectedDoc;
         return !targetDoc ? (null) : <Tooltip
             title={<><div className="dash-tooltip">{"Download Document"}</div></>}>
-            <div className={"documentButtonBar-linkButton-empty"}
+            <div className={"propertiesButtons-linkButton-empty"}
                 onPointerDown={async () => {
                     if (this.selectedDocumentView?.props.Document) {
                         Doc.Zip(this.selectedDocumentView?.props.Document);
                     }
                 }}>
-                {<FontAwesomeIcon className="documentdecorations-icon"
+                {<FontAwesomeIcon className="propertiesButtons-icon"
                     icon="download" size="sm" />}
             </div>
         </Tooltip>;
@@ -332,11 +332,11 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         const targetDoc = this.selectedDoc;
         return !targetDoc ? (null) : <Tooltip
             title={<><div className="dash-tooltip">{"Delete Document"}</div></>}>
-            <div className={"documentButtonBar-linkButton-empty"}
+            <div className={"propertiesButtons-linkButton-empty"}
                 onPointerDown={() => {
                     this.selectedDocumentView?.props.ContainingCollectionView?.removeDocument(this.selectedDocumentView?.props.Document);
                 }}>
-                {<FontAwesomeIcon className="documentdecorations-icon"
+                {<FontAwesomeIcon className="propertiesButtons-icon"
                     icon="trash-alt" size="sm" />}
             </div>
         </Tooltip>;
@@ -347,13 +347,13 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         const targetDoc = this.selectedDoc;
         return !targetDoc ? (null) : <Tooltip
             title={<><div className="dash-tooltip">{"Share Document"}</div></>}>
-            <div className={"documentButtonBar-linkButton-empty"}
+            <div className={"propertiesButtons-linkButton-empty"}
                 onPointerDown={() => {
                     if (this.selectedDocumentView) {
                         SharingManager.Instance.open(this.selectedDocumentView);
                     }
                 }}>
-                {<FontAwesomeIcon className="documentdecorations-icon"
+                {<FontAwesomeIcon className="propertiesButtons-icon"
                     icon="users" size="sm" />}
             </div>
         </Tooltip>;
@@ -379,21 +379,21 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     @action
     handleOptionChange = (e: any) => {
         const value = e.target.value;
-        this.selectedDoc?.onClickBehavior = e.target.value;
+        this.selectedDoc && (this.selectedDoc.onClickBehavior = e.target.value);
         if (value === "nothing") {
-            this.selectedDocumentView?.noOnClick;
+            this.selectedDocumentView?.noOnClick();
         } else if (value === "enterPortal") {
-            //this.selectedDocumentView?.noOnClick;
-            this.selectedDocumentView?.makeIntoPortal;
+            this.selectedDocumentView?.noOnClick();
+            this.selectedDocumentView?.makeIntoPortal();
         } else if (value === "toggleDetail") {
-            //this.selectedDocumentView?.noOnClick;
-            this.selectedDocumentView?.toggleDetail;
+            this.selectedDocumentView?.noOnClick();
+            this.selectedDocumentView?.toggleDetail();
         } else if (value === "linkInPlace") {
-            //this.selectedDocumentView?.noOnClick;
-            this.selectedDocumentView?.toggleFollowInPlace;
+            this.selectedDocumentView?.noOnClick();
+            this.selectedDocumentView?.toggleFollowInPlace();
         } else if (value === "linkOnRight") {
-            //this.selectedDocumentView?.noOnClick;
-            this.selectedDocumentView?.toggleFollowOnRight;
+            this.selectedDocumentView?.noOnClick();
+            this.selectedDocumentView?.toggleFollowOnRight();
         }
     }
 
@@ -457,7 +457,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         const targetDoc = this.selectedDoc;
         return !targetDoc ? (null) : <Tooltip
             title={<><div className="dash-tooltip">{"Export to Google Photos"}</div></>}>
-            <div className={"documentButtonBar-linkButton-empty"}
+            <div className={"propertiesButtons-linkButton-empty"}
                 onPointerDown={() => {
                     if (this.selectedDocumentView) {
                         GooglePhotos.Export.CollectionToAlbum({ collection: this.selectedDocumentView.Document }).then(console.log)
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index 8cc591875..0701f3b96 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -196,6 +196,16 @@
         }
     }
 
+    .field {
+        display: flex;
+        font-size: 7px;
+        background-color: #e8e8e8;
+        padding-right: 3px;
+        border: 0.5px solid grey;
+        border-radius: 5px;
+        padding-left: 3px;
+    }
+
     .propertiesView-layout {
         padding: 8.5px;
 
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 3b8d782aa..0f59e2f79 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -113,6 +113,19 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                     {contentElement}
                 </div>);
             }
+
+            rows.push(<div className="field" key={"newKeyValue"}>
+                <EditableView
+                    key="editableView"
+                    contents={"add key:value"}
+                    height={13}
+                    fontSize={12}
+                    GetValue={() => ""}
+                    SetValue={(value: string) => {
+                        value.indexOf(":") !== -1 && KeyValueBox.SetField(doc, value.substring(0, value.indexOf(":")), value.substring(value.indexOf(":") + 1, value.length), true);
+                        return true;
+                    }} />
+            </div>);
             return rows;
         }
     }
-- 
cgit v1.2.3-70-g09d2


From e7af5195af8a7e0cfe1bcd40d49859474568a739 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Tue, 28 Jul 2020 13:41:59 -0500
Subject: novice mode for fields and tagging and view only fields

---
 .../collectionFreeForm/PropertiesView.scss         |  12 +++
 .../collectionFreeForm/PropertiesView.tsx          | 119 +++++++++++++++++----
 2 files changed, 108 insertions(+), 23 deletions(-)

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

diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index 0701f3b96..856f8e7f2 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -170,6 +170,8 @@
             .propertiesView-fields-title-name {
                 font-size: 12.5px;
                 font-weight: bold;
+                white-space: nowrap;
+                width: 35px;
             }
 
             .propertiesView-fields-title-checkbox {
@@ -206,6 +208,16 @@
         padding-left: 3px;
     }
 
+    .uneditable-field {
+        display: flex;
+        overflow-y: visible;
+        margin-bottom: 2px;
+
+        &:hover {
+            cursor: auto;
+        }
+    }
+
     .propertiesView-layout {
         padding: 8.5px;
 
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 0f59e2f79..be024b772 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -7,7 +7,7 @@ import { DocumentView } from "../../nodes/DocumentView";
 import { ComputedField } from "../../../../fields/ScriptField";
 import { EditableView } from "../../EditableView";
 import { KeyValueBox } from "../../nodes/KeyValueBox";
-import { Cast, StrCast, NumCast } from "../../../../fields/Types";
+import { Cast, NumCast, StrCast } from "../../../../fields/Types";
 import { listSpec } from "../../../../fields/Schema";
 import { ContentFittingDocumentView } from "../../nodes/ContentFittingDocumentView";
 import { returnFalse, returnOne, emptyFunction, emptyPath, returnTrue, returnZero, returnEmptyFilter, Utils } from "../../../../Utils";
@@ -94,42 +94,113 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
             const ids: { [key: string]: string } = {};
             const doc = this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc;
             doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key));
-
             const rows: JSX.Element[] = [];
             for (const key of Object.keys(ids).slice().sort()) {
                 const contents = doc[key];
-                let contentElement: (JSX.Element | null)[] | JSX.Element = [];
-                contentElement = <EditableView key="editableView"
-                    contents={contents !== undefined ? Field.toString(contents as Field) : "null"}
+                if (contents === "UNDEFINED") {
+                    rows.push(<div style={{ display: "flex", overflowY: "visible", marginBottom: "2px" }} key={key}>
+                        <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key}</span>
+                    &nbsp;
+                </div>);
+                } else {
+                    let contentElement: (JSX.Element | null)[] | JSX.Element = [];
+                    contentElement = <EditableView key="editableView"
+                        contents={contents !== undefined ? Field.toString(contents as Field) : "null"}
+                        height={13}
+                        fontSize={10}
+                        GetValue={() => Field.toKeyValueString(doc, key)}
+                        SetValue={(value: string) => KeyValueBox.SetField(doc, key, value, true)}
+                    />;
+                    rows.push(<div style={{ display: "flex", overflowY: "visible", marginBottom: "-1px" }} key={key}>
+                        <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key + ":"}</span>
+                        &nbsp;
+                        {contentElement}
+                    </div>);
+                }
+            }
+            rows.push(<div className="field" key={"newKeyValue"} style={{ marginTop: "3px" }}>
+                <EditableView
+                    key="editableView"
+                    contents={"add key:value or #tags"}
                     height={13}
                     fontSize={10}
-                    GetValue={() => Field.toKeyValueString(doc, key)}
-                    SetValue={(value: string) => KeyValueBox.SetField(doc, key, value, true)}
-                />;
+                    GetValue={() => ""}
+                    SetValue={this.setKeyValue} />
+            </div>);
+            return rows;
+        }
+    }
 
-                rows.push(<div style={{ display: "flex", overflowY: "visible", marginBottom: "-1px" }} key={key}>
-                    <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key + ":"}</span>
+    @computed get noviceFields() {
+        if (this.dataDoc && this.selectedDoc) {
+            const ids: { [key: string]: string } = {};
+            const doc = this.dataDoc;
+            doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key));
+            const rows: JSX.Element[] = [];
+            for (const key of Object.keys(ids).slice().sort()) {
+                if (key[0] === key[0].toUpperCase() || key[0] === "#" || key === "author" || key === "creationDate" || key.indexOf("lastModified") !== -1) {
+                    const contents = doc[key];
+                    if (contents === "UNDEFINED") {
+                        rows.push(<div className="uneditable-field" key={key}>
+                            <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key}</span>
                     &nbsp;
-                    {contentElement}
                 </div>);
-            }
+                    } else {
+                        const value = Field.toString(contents as Field);
+                        if (key === "author" || key === "creationDate" || key.indexOf("lastModified") !== -1) {
+                            rows.push(<div className="uneditable-field" key={key}>
+                                <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key + ": "}</span>
+                                <div style={{ whiteSpace: "nowrap", overflowX: "hidden" }}>{value}</div>
+                            </div>);
+                        } else {
+                            let contentElement: (JSX.Element | null)[] | JSX.Element = [];
+                            contentElement = <EditableView key="editableView"
+                                contents={contents !== undefined ? Field.toString(contents as Field) : "null"}
+                                height={13}
+                                fontSize={10}
+                                GetValue={() => Field.toKeyValueString(doc, key)}
+                                SetValue={(value: string) => KeyValueBox.SetField(doc, key, value, true)}
+                            />;
 
-            rows.push(<div className="field" key={"newKeyValue"}>
+                            rows.push(<div style={{ display: "flex", overflowY: "visible", marginBottom: "-1px" }} key={key}>
+                                <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key + ":"}</span>
+                            &nbsp;
+                            {contentElement}
+                            </div>);
+                        }
+                    }
+                }
+            }
+            rows.push(<div className="field" key={"newKeyValue"} style={{ marginTop: "3px" }}>
                 <EditableView
                     key="editableView"
-                    contents={"add key:value"}
+                    contents={"add key:value or #tags"}
                     height={13}
-                    fontSize={12}
+                    fontSize={10}
                     GetValue={() => ""}
-                    SetValue={(value: string) => {
-                        value.indexOf(":") !== -1 && KeyValueBox.SetField(doc, value.substring(0, value.indexOf(":")), value.substring(value.indexOf(":") + 1, value.length), true);
-                        return true;
-                    }} />
+                    SetValue={this.setKeyValue} />
             </div>);
             return rows;
         }
     }
 
+
+    setKeyValue = (value: string) => {
+        if (this.selectedDoc && this.dataDoc) {
+            const doc = this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc;
+            if (value.indexOf(":") !== -1) {
+                const newVal = value[0].toUpperCase() + value.substring(1, value.length);
+                KeyValueBox.SetField(doc, newVal.substring(0, newVal.indexOf(":")), newVal.substring(newVal.indexOf(":") + 1, newVal.length), true);
+                return true;
+            } else if (value[0] === "#") {
+                const newVal = value + ":'UNDEFINED'";
+                KeyValueBox.SetField(doc, newVal.substring(0, newVal.indexOf(":")), newVal.substring(newVal.indexOf(":") + 1, newVal.length), true);
+                return true;
+            }
+        }
+        return false;
+    }
+
     @computed get layoutPreview() {
         if (this.selectedDoc) {
             const layoutDoc = Doc.Layout(this.selectedDoc);
@@ -252,6 +323,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
             </div> </div>;
         }
 
+        const novice = Doc.UserDoc().noviceMode;
+
         return <div className="propertiesView" >
             <div className="propertiesView-title">
                 <div className="propertiesView-title-name">Properties </div>
@@ -277,14 +350,14 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
             <div className="propertiesView-fields">
                 <div className="propertiesView-fields-title">
                     <div className="propertiesView-fields-title-name">
-                        Fields
+                        Fields {"&"} Tags
                     </div>
-                    <div className="propertiesView-fields-title-checkbox">
+                    {!novice ? <div className="propertiesView-fields-title-checkbox">
                         {this.fieldsCheckbox}
                         <div className="propertiesView-fields-title-checkbox-text">Layout</div>
-                    </div>
+                    </div> : null}
                 </div>
-                <div className="propertiesView-fields-content"> {this.expandedField} </div>
+                <div className="propertiesView-fields-content"> {novice ? this.noviceFields : this.expandedField} </div>
             </div>
             <div className="propertiesView-layout">
                 <div className="propertiesView-layout-title" >Layout</div>
-- 
cgit v1.2.3-70-g09d2


From f19ee5abb19ece29a0ea7a857078125307f15908 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Tue, 28 Jul 2020 16:36:15 -0500
Subject: collapsing sections

---
 src/client/views/DocumentDecorations.tsx           |  2 +-
 .../collectionFreeForm/PropertiesView.scss         | 45 +++++++++++++
 .../collectionFreeForm/PropertiesView.tsx          | 73 ++++++++++++++++++----
 3 files changed, 107 insertions(+), 13 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index c889557ba..0a0136d87 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -577,7 +577,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             </> :
             <>
                 {minimal ? (null) : <Tooltip title={<><div className="dash-tooltip">Show context menu</div></>} placement="top"><div className="documentDecorations-contextMenu" key="menu" onPointerDown={this.onSettingsDown}>
-                    <FontAwesomeIcon size="lg" icon="cog" />
+                    <FontAwesomeIcon size="lg" icon="bars" />
                 </div></Tooltip>}
                 <div className="documentDecorations-title" key="title" onPointerDown={this.onTitleDown} >
                     <span style={{ width: "100%", display: "inline-block", cursor: "move" }}>{`${this.selectionTitle}`}</span>
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index 856f8e7f2..1fda8e5a2 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -40,6 +40,10 @@
         border-bottom: 1px solid black;
         padding: 8.5px;
         font-size: 12.5px;
+
+        &:hover {
+            cursor: pointer;
+        }
     }
 
     .propertiesView-settings {
@@ -52,6 +56,17 @@
             font-weight: bold;
             font-size: 12.5px;
             padding-bottom: 7px;
+            display: flex;
+            width: 200px;
+
+            .propertiesView-settings-title-icon {
+                margin-left: 2px;
+                margin-right: 7px;
+
+                &:hover {
+                    cursor: pointer;
+                }
+            }
         }
 
         .propertiesView-settings-content {
@@ -69,6 +84,16 @@
             font-size: 12.5px;
             font-weight: bold;
             padding-bottom: 7px;
+            display: flex;
+
+            .propertiesView-sharing-title-icon {
+                margin-left: 2px;
+                margin-right: 7px;
+
+                &:hover {
+                    cursor: pointer;
+                }
+            }
         }
 
         .propertiesView-sharing-content {
@@ -172,6 +197,16 @@
                 font-weight: bold;
                 white-space: nowrap;
                 width: 35px;
+                display: flex;
+            }
+
+            .propertiesView-fields-title-icon {
+                margin-left: 2px;
+                margin-right: 7px;
+
+                &:hover {
+                    cursor: pointer;
+                }
             }
 
             .propertiesView-fields-title-checkbox {
@@ -225,6 +260,16 @@
             font-weight: bold;
             font-size: 12.5px;
             padding-bottom: 7px;
+            display: flex;
+
+            .propertiesView-layout-title-icon {
+                margin-left: 2px;
+                margin-right: 7px;
+
+                &:hover {
+                    cursor: pointer;
+                }
+            }
         }
 
         .propertiesView-layout-content {
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index be024b772..91d407eea 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -1,7 +1,7 @@
 import React = require("react");
 import { observer } from "mobx-react";
 import "./PropertiesView.scss";
-import { observable, action, computed } from "mobx";
+import { observable, action, computed, runInAction } from "mobx";
 import { Doc, Field, DocListCast, WidthSym, HeightSym } from "../../../../fields/Doc";
 import { DocumentView } from "../../nodes/DocumentView";
 import { ComputedField } from "../../../../fields/ScriptField";
@@ -43,6 +43,11 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     @observable layoutFields: boolean = false;
 
+    @observable openActions: boolean = true;
+    @observable openSharing: boolean = true;
+    @observable openFields: boolean = true;
+    @observable openLayout: boolean = true;
+
     @action
     rtfWidth = () => {
         if (this.selectedDoc) {
@@ -314,6 +319,25 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         this.layoutFields = !this.layoutFields;
     }
 
+    @computed get editableTitle() {
+        return <EditableView
+            key="editableView"
+            contents={StrCast(this.selectedDoc?.title)}
+            height={25}
+            fontSize={14}
+            GetValue={() => StrCast(this.selectedDoc?.title)}
+            SetValue={this.setTitle} />;
+    }
+
+    setTitle = (value: string) => {
+        if (this.dataDoc) {
+            this.selectedDoc && (this.selectedDoc.title = value);
+            KeyValueBox.SetField(this.dataDoc, "title", value, true);
+            return true;
+        }
+        return false;
+    }
+
     render() {
 
         if (!this.selectedDoc) {
@@ -333,35 +357,60 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 </div>
             </div>
             <div className="propertiesView-name">
-                {this.selectedDoc.title}
+                {this.editableTitle}
             </div>
             <div className="propertiesView-settings">
-                <div className="propertiesView-settings-title"> Document Actions </div>
-                <div className="propertiesView-settings-content">
-                    <PropertiesButtons />
+                <div className="propertiesView-settings-title">
+                    <div className="propertiesView-settings-title-icon"
+                        onPointerDown={() => runInAction(() => { this.openActions = !this.openActions; })}>
+                        <FontAwesomeIcon icon={this.openActions ? "caret-down" : "caret-right"} size="lg" color="black" />
+                    </div>
+                    Document Actions
                 </div>
+                {this.openActions ? <div className="propertiesView-settings-content">
+                    <PropertiesButtons />
+                </div> : null}
             </div>
             <div className="propertiesView-sharing">
-                <div className="propertiesView-sharing-title"> Sharing {"&"} Permissions</div>
-                <div className="propertiesView-sharing-content">
-                    {this.sharingTable}
+                <div className="propertiesView-sharing-title">
+                    <div className="propertiesView-sharing-title-icon"
+                        onPointerDown={() => runInAction(() => { this.openSharing = !this.openSharing; })}>
+                        <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="black" />
+                    </div>
+                    Sharing {"&"} Permissions
                 </div>
+                {this.openSharing ? <div className="propertiesView-sharing-content">
+                    {this.sharingTable}
+                </div> : null}
             </div>
             <div className="propertiesView-fields">
                 <div className="propertiesView-fields-title">
                     <div className="propertiesView-fields-title-name">
+                        <div className="propertiesView-fields-title-icon"
+                            onPointerDown={() => runInAction(() => { this.openFields = !this.openFields; })}>
+                            <FontAwesomeIcon icon={this.openFields ? "caret-down" : "caret-right"} size="lg" color="black" />
+                        </div>
                         Fields {"&"} Tags
                     </div>
-                    {!novice ? <div className="propertiesView-fields-title-checkbox">
+                    {!novice && this.openFields ? <div className="propertiesView-fields-title-checkbox">
                         {this.fieldsCheckbox}
                         <div className="propertiesView-fields-title-checkbox-text">Layout</div>
                     </div> : null}
                 </div>
-                <div className="propertiesView-fields-content"> {novice ? this.noviceFields : this.expandedField} </div>
+                {this.openFields ?
+                    <div className="propertiesView-fields-content">
+                        {novice ? this.noviceFields : this.expandedField}
+                    </div> : null}
             </div>
             <div className="propertiesView-layout">
-                <div className="propertiesView-layout-title" >Layout</div>
-                <div className="propertiesView-layout-content">{this.layoutPreview}</div>
+                <div className="propertiesView-layout-title" >
+                    <div className="propertiesView-layout-title-icon"
+                        onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}>
+                        <FontAwesomeIcon icon={this.openLayout ? "caret-down" : "caret-right"} size="lg" color="black" />
+                    </div>
+                    Layout
+                </div>
+                {this.openLayout ? <div className="propertiesView-layout-content">{this.layoutPreview}</div> : null}
             </div>
         </div>;
     }
-- 
cgit v1.2.3-70-g09d2


From 155407d902bac7a82a83ba2f60f05a6fddb0d6e6 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Tue, 28 Jul 2020 20:59:45 -0500
Subject: new UI for collapsing

---
 src/client/views/PropertiesButtons.tsx             |  2 +-
 .../collectionFreeForm/PropertiesView.scss         | 66 +++++++++++++++-------
 .../collectionFreeForm/PropertiesView.tsx          | 32 +++++------
 3 files changed, 64 insertions(+), 36 deletions(-)

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

diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index 95d0df14e..eecf670e6 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -206,7 +206,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         const isPinned = targetDoc && Doc.isDocPinned(targetDoc);
         return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}</div></>}>
             <div className="propertiesButtons-linker"
-                style={{ backgroundColor: isPinned ? "white" : "#121721", color: isPinned ? "black" : "white" }}
+                style={{ backgroundColor: isPinned ? "white" : "rgb(37, 43, 51)", color: isPinned ? "black" : "white" }}
                 onClick={e => DockedFrameRenderer.PinDoc(targetDoc, isPinned)}>
                 <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin"
                 />
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index 1fda8e5a2..cb4b7375b 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -48,20 +48,26 @@
 
     .propertiesView-settings {
         border-bottom: 1px solid black;
-        padding: 8.5px;
+        //padding: 8.5px;
         font-size: 12.5px;
         font-weight: bold;
 
         .propertiesView-settings-title {
             font-weight: bold;
             font-size: 12.5px;
-            padding-bottom: 7px;
+            padding: 4px;
             display: flex;
             width: 200px;
+            color: white;
+            padding-left: 8px;
+            background-color: rgb(51, 51, 51);
 
             .propertiesView-settings-title-icon {
+                float: right;
+                right: 0;
+                position: absolute;
                 margin-left: 2px;
-                margin-right: 7px;
+                margin-right: 9px;
 
                 &:hover {
                     cursor: pointer;
@@ -70,25 +76,33 @@
         }
 
         .propertiesView-settings-content {
-            margin-left: 5px;
+            margin-left: 12px;
             padding-bottom: 10px;
+            padding-top: 8px;
         }
 
     }
 
     .propertiesView-sharing {
         border-bottom: 1px solid black;
-        padding: 8.5px;
+        //padding: 8.5px;
 
         .propertiesView-sharing-title {
-            font-size: 12.5px;
             font-weight: bold;
-            padding-bottom: 7px;
+            font-size: 12.5px;
+            padding: 4px;
             display: flex;
+            width: 200px;
+            color: white;
+            padding-left: 8px;
+            background-color: rgb(51, 51, 51);
 
             .propertiesView-sharing-title-icon {
+                float: right;
+                right: 0;
+                position: absolute;
                 margin-left: 2px;
-                margin-right: 7px;
+                margin-right: 9px;
 
                 &:hover {
                     cursor: pointer;
@@ -98,6 +112,7 @@
 
         .propertiesView-sharing-content {
             font-size: 10px;
+            padding: 10px;
             margin-left: 5px;
         }
     }
@@ -165,9 +180,6 @@
 
                 .permissions-select {
                     z-index: 1;
-                    //border: 0.5px solid grey;
-                    //border-radius: 4px;
-                    //outline: none;
                     border: none;
                     background-color: inherit;
                     width: 75px;
@@ -186,11 +198,17 @@
 
     .propertiesView-fields {
         border-bottom: 1px solid black;
-        padding: 8.5px;
+        //padding: 8.5px;
 
         .propertiesView-fields-title {
-            padding-bottom: 7px;
+            font-weight: bold;
+            font-size: 12.5px;
+            padding: 4px;
             display: flex;
+            width: 200px;
+            color: white;
+            padding-left: 8px;
+            background-color: rgb(51, 51, 51);
 
             .propertiesView-fields-title-name {
                 font-size: 12.5px;
@@ -201,8 +219,11 @@
             }
 
             .propertiesView-fields-title-icon {
+                float: right;
+                right: 0;
+                position: absolute;
                 margin-left: 2px;
-                margin-right: 7px;
+                margin-right: 9px;
 
                 &:hover {
                     cursor: pointer;
@@ -225,7 +246,8 @@
 
         .propertiesView-fields-content {
             font-size: 10px;
-            margin-left: 5px;
+            margin-left: 2px;
+            padding: 10px;
 
             &:hover {
                 cursor: pointer;
@@ -254,17 +276,23 @@
     }
 
     .propertiesView-layout {
-        padding: 8.5px;
 
         .propertiesView-layout-title {
             font-weight: bold;
             font-size: 12.5px;
-            padding-bottom: 7px;
+            padding: 4px;
             display: flex;
+            width: 200px;
+            color: white;
+            padding-left: 8px;
+            background-color: rgb(51, 51, 51);
 
             .propertiesView-layout-title-icon {
+                float: right;
+                right: 0;
+                position: absolute;
                 margin-left: 2px;
-                margin-right: 7px;
+                margin-right: 9px;
 
                 &:hover {
                     cursor: pointer;
@@ -273,8 +301,8 @@
         }
 
         .propertiesView-layout-content {
-            margin-left: 5px;
             overflow: hidden;
+            padding: 10px;
         }
 
     }
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 91d407eea..d5317efcb 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -360,55 +360,55 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 {this.editableTitle}
             </div>
             <div className="propertiesView-settings">
-                <div className="propertiesView-settings-title">
+                <div className="propertiesView-settings-title" style={{ backgroundColor: this.openActions ? "black" : "" }}>
+                    Document Actions
                     <div className="propertiesView-settings-title-icon"
                         onPointerDown={() => runInAction(() => { this.openActions = !this.openActions; })}>
-                        <FontAwesomeIcon icon={this.openActions ? "caret-down" : "caret-right"} size="lg" color="black" />
+                        <FontAwesomeIcon icon={this.openActions ? "caret-down" : "caret-right"} size="lg" color="white" />
                     </div>
-                    Document Actions
                 </div>
                 {this.openActions ? <div className="propertiesView-settings-content">
                     <PropertiesButtons />
                 </div> : null}
             </div>
             <div className="propertiesView-sharing">
-                <div className="propertiesView-sharing-title">
+                <div className="propertiesView-sharing-title" style={{ backgroundColor: this.openSharing ? "black" : "" }}>
+                    Sharing {"&"} Permissions
                     <div className="propertiesView-sharing-title-icon"
                         onPointerDown={() => runInAction(() => { this.openSharing = !this.openSharing; })}>
-                        <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="black" />
+                        <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="white" />
                     </div>
-                    Sharing {"&"} Permissions
                 </div>
                 {this.openSharing ? <div className="propertiesView-sharing-content">
                     {this.sharingTable}
                 </div> : null}
             </div>
             <div className="propertiesView-fields">
-                <div className="propertiesView-fields-title">
+                <div className="propertiesView-fields-title" style={{ backgroundColor: this.openFields ? "black" : "" }}>
                     <div className="propertiesView-fields-title-name">
+                        Fields {"&"} Tags
                         <div className="propertiesView-fields-title-icon"
                             onPointerDown={() => runInAction(() => { this.openFields = !this.openFields; })}>
-                            <FontAwesomeIcon icon={this.openFields ? "caret-down" : "caret-right"} size="lg" color="black" />
+                            <FontAwesomeIcon icon={this.openFields ? "caret-down" : "caret-right"} size="lg" color="white" />
                         </div>
-                        Fields {"&"} Tags
                     </div>
-                    {!novice && this.openFields ? <div className="propertiesView-fields-title-checkbox">
-                        {this.fieldsCheckbox}
-                        <div className="propertiesView-fields-title-checkbox-text">Layout</div>
-                    </div> : null}
                 </div>
+                {!novice && this.openFields ? <div className="propertiesView-fields-title-checkbox">
+                    {this.fieldsCheckbox}
+                    <div className="propertiesView-fields-title-checkbox-text">Layout</div>
+                </div> : null}
                 {this.openFields ?
                     <div className="propertiesView-fields-content">
                         {novice ? this.noviceFields : this.expandedField}
                     </div> : null}
             </div>
             <div className="propertiesView-layout">
-                <div className="propertiesView-layout-title" >
+                <div className="propertiesView-layout-title" style={{ backgroundColor: this.openLayout ? "black" : "" }}>
+                    Layout
                     <div className="propertiesView-layout-title-icon"
                         onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}>
-                        <FontAwesomeIcon icon={this.openLayout ? "caret-down" : "caret-right"} size="lg" color="black" />
+                        <FontAwesomeIcon icon={this.openLayout ? "caret-down" : "caret-right"} size="lg" color="white" />
                     </div>
-                    Layout
                 </div>
                 {this.openLayout ? <div className="propertiesView-layout-content">{this.layoutPreview}</div> : null}
             </div>
-- 
cgit v1.2.3-70-g09d2


From 611f848ff4f7b958dc913d33dd1b760ca9474c44 Mon Sep 17 00:00:00 2001
From: usodhi <61431818+usodhi@users.noreply.github.com>
Date: Thu, 30 Jul 2020 18:33:19 +0530
Subject: permissions from the properties panel should work now

---
 src/client/util/GroupManager.tsx                   |  2 +-
 src/client/util/SharingManager.tsx                 | 29 +++++++----
 .../collectionFreeForm/PropertiesView.scss         |  2 +
 .../collectionFreeForm/PropertiesView.tsx          | 56 ++++++++++++++--------
 src/fields/util.ts                                 | 12 ++++-
 5 files changed, 67 insertions(+), 34 deletions(-)

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

diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx
index 72fba5c1b..dee0f105f 100644
--- a/src/client/util/GroupManager.tsx
+++ b/src/client/util/GroupManager.tsx
@@ -101,7 +101,7 @@ export default class GroupManager extends React.Component<{}> {
      */
     @action
     open = () => {
-        SelectionManager.DeselectAll();
+        // SelectionManager.DeselectAll();
         this.isOpen = true;
         this.populateUsers();
         this.populateGroups();
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index 0d8b33fbe..9222f10c5 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -62,14 +62,12 @@ export default class SharingManager extends React.Component<{}> {
     @observable private groupSort: "ascending" | "descending" | "none" = "none";
     private shareDocumentButtonRef: React.RefObject<HTMLButtonElement> = React.createRef();
 
-
-
     // private get linkVisible() {
     //     return this.sharingDoc ? this.sharingDoc[PublicKey] !== SharingPermissions.None : false;
     // }
 
     public open = (target: DocumentView) => {
-        SelectionManager.DeselectAll();
+        // SelectionManager.DeselectAll();
         this.populateUsers().then(action(() => {
             this.targetDocView = target;
             this.targetDoc = target.props.Document;
@@ -82,7 +80,7 @@ export default class SharingManager extends React.Component<{}> {
 
     public close = action(() => {
         this.isOpen = false;
-        this.users = [];
+        // this.users = [];
         this.selectedUsers = null;
 
         setTimeout(action(() => {
@@ -97,7 +95,12 @@ export default class SharingManager extends React.Component<{}> {
         SharingManager.Instance = this;
     }
 
+    componentDidMount() {
+        this.populateUsers();
+    }
+
     populateUsers = async () => {
+        runInAction(() => this.users = []);
         const userList = await RequestPromise.get(Utils.prepend("/getUsers"));
         const raw = JSON.parse(userList) as User[];
         const evaluating = raw.map(async user => {
@@ -117,17 +120,17 @@ export default class SharingManager extends React.Component<{}> {
         return Promise.all(evaluating);
     }
 
-    setInternalGroupSharing = (group: Doc, permission: string) => {
+    setInternalGroupSharing = (group: Doc, permission: string, targetDoc?: Doc) => {
         const members: string[] = JSON.parse(StrCast(group.members));
         const users: ValidatedUser[] = this.users.filter(({ user: { email } }) => members.includes(email));
 
-        const target = this.targetDoc!;
+        const target = targetDoc || this.targetDoc!;
         const ACL = `ACL-${StrCast(group.groupName)}`;
         // fix this - not needed (here and setinternalsharing and removegroup)
         // target[ACL] = permission;
         // Doc.GetProto(target)[ACL] = permission;
 
-        distributeAcls(ACL, permission as SharingPermissions, this.targetDoc!);
+        distributeAcls(ACL, permission as SharingPermissions, target);
 
         group.docsShared ? DocListCastAsync(group.docsShared).then(resolved => Doc.IndexOf(target, resolved!) === -1 && (group.docsShared as List<Doc>).push(target)) : group.docsShared = new List<Doc>([target]);
 
@@ -182,14 +185,20 @@ export default class SharingManager extends React.Component<{}> {
         }
     }
 
+    shareFromPropertiesSidebar = (shareWith: string, permission: SharingPermissions, target: Doc) => {
+        const user = this.users.find(({ user: { email } }) => email === (shareWith === "Me" ? Doc.CurrentUserEmail : shareWith));
+        if (user) this.setInternalSharing(user, permission, target);
+        else this.setInternalGroupSharing(GroupManager.Instance.getGroup(shareWith)!, permission, target);
+    }
+
     // @action
-    setInternalSharing = (recipient: ValidatedUser, permission: string) => {
+    setInternalSharing = (recipient: ValidatedUser, permission: string, targetDoc?: Doc) => {
         const { user, notificationDoc } = recipient;
-        const target = this.targetDoc!;
+        const target = targetDoc || this.targetDoc!;
         const key = user.email.replace('.', '_');
         const ACL = `ACL-${key}`;
 
-        distributeAcls(ACL, permission as SharingPermissions, this.targetDoc!);
+        distributeAcls(ACL, permission as SharingPermissions, target);
 
         if (permission !== SharingPermissions.None) {
             DocListCastAsync(notificationDoc[storage]).then(resolved => {
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index cb4b7375b..4ccc0950b 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -159,6 +159,8 @@
         border-radius: 6px;
         width: 170px;
         background-color: #ececec;
+        max-height: 130px;
+        overflow-y: scroll;
 
         .propertiesView-sharingTable-item {
 
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index d5317efcb..b33b37f4b 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -2,7 +2,7 @@ import React = require("react");
 import { observer } from "mobx-react";
 import "./PropertiesView.scss";
 import { observable, action, computed, runInAction } from "mobx";
-import { Doc, Field, DocListCast, WidthSym, HeightSym } from "../../../../fields/Doc";
+import { Doc, Field, DocListCast, WidthSym, HeightSym, AclSym, AclPrivate, AclReadonly, AclAddonly, AclEdit, AclAdmin } from "../../../../fields/Doc";
 import { DocumentView } from "../../nodes/DocumentView";
 import { ComputedField } from "../../../../fields/ScriptField";
 import { EditableView } from "../../EditableView";
@@ -18,6 +18,7 @@ import { SelectionManager } from "../../../util/SelectionManager";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { Tooltip, Checkbox } from "@material-ui/core";
 import SharingManager from "../../../util/SharingManager";
+import { SharingPermissions, GetEffectiveAcl } from "../../../../fields/util";
 
 
 interface PropertiesViewProps {
@@ -249,20 +250,15 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         }
     }
 
-    @computed get permissionsSelect() {
-        return <select className="permissions-select" onChange={emptyFunction}>
-            <option key={"Can Edit"} value={"Can Edit"}>
-                Can Edit
-                        </option>
-            <option key={"Can Add"} value={"Can Add"}>
-                Can Add
-                        </option>
-            <option key={"Can View"} value={"Can View"}>
-                Can View
-                        </option>
-            <option key={"Not Shared"} value={"Not Shared"}>
-                Not Shared
-                        </option>
+    getPermissionsSelect(user: string) {
+        return <select className="permissions-select"
+            onChange={e => SharingManager.Instance.shareFromPropertiesSidebar(user, e.currentTarget.value as SharingPermissions, this.selectedDoc!)}>
+            {Object.values(SharingPermissions).map(permission => {
+                return (
+                    <option key={permission} value={permission} selected={this.selectedDoc![`ACL-${user.replace(".", "_")}`] === permission}>
+                        {permission}
+                    </option>);
+            })}
         </select>;
     }
 
@@ -286,23 +282,41 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         </Tooltip>;
     }
 
-    sharingItem(name: string, notify: boolean, editable: boolean, permission?: string) {
+    sharingItem(name: string, notify: boolean, effectiveAcl: symbol, permission?: string) {
         return <div className="propertiesView-sharingTable-item">
             <div className="propertiesView-sharingTable-item-name" style={{ width: notify ? "70px" : "80px" }}> {name} </div>
             {notify ? this.notifyIcon : null}
             <div className="propertiesView-sharingTable-item-permission">
-                {editable ? this.permissionsSelect : permission}
+                {effectiveAcl === AclAdmin && permission !== "Owner" ? this.getPermissionsSelect(name) : permission}
                 {permission === "Owner" ? this.expansionIcon : null}
             </div>
         </div>;
     }
 
     @computed get sharingTable() {
+        const AclMap = new Map<symbol, string>([
+            [AclPrivate, SharingPermissions.None],
+            [AclReadonly, SharingPermissions.View],
+            [AclAddonly, SharingPermissions.Add],
+            [AclEdit, SharingPermissions.Edit],
+            [AclAdmin, SharingPermissions.Admin]
+        ]);
+
+        const effectiveAcl = GetEffectiveAcl(this.selectedDoc!);
+        const tableEntries = [];
+
+        if (this.selectedDoc![AclSym]) {
+            for (const [key, value] of Object.entries(this.selectedDoc![AclSym])) {
+                const name = key.substring(4).replace("_", ".");
+                if (name !== Doc.CurrentUserEmail && name !== this.selectedDoc!.author) tableEntries.push(this.sharingItem(name, false, effectiveAcl, AclMap.get(value)!));
+            }
+        }
+
+        tableEntries.unshift(this.sharingItem("Me", false, effectiveAcl, Doc.CurrentUserEmail === this.selectedDoc!.author ? "Owner" : StrCast(this.selectedDoc![`ACL-${Doc.CurrentUserEmail.replace(".", "_")}`])));
+        if (Doc.CurrentUserEmail !== this.selectedDoc!.author) tableEntries.unshift(this.sharingItem(StrCast(this.selectedDoc!.author), false, effectiveAcl, "Owner"));
+
         return <div className="propertiesView-sharingTable">
-            {this.sharingItem("Me", false, false, "Owner")}
-            {this.sharingItem("Public", false, true)}
-            {this.sharingItem("Group 1", true, true)}
-            {this.sharingItem("Group 2", true, true)}
+            {tableEntries}
         </div>;
     }
 
diff --git a/src/fields/util.ts b/src/fields/util.ts
index a62795e64..267da70b4 100644
--- a/src/fields/util.ts
+++ b/src/fields/util.ts
@@ -1,5 +1,5 @@
 import { UndoManager } from "../client/util/UndoManager";
-import { Doc, FieldResult, UpdatingFromServer, LayoutSym, AclPrivate, AclEdit, AclReadonly, AclAddonly, AclSym, CachedUpdates, DataSym, DocListCast, AclAdmin, FieldsSym, HeightSym, WidthSym } from "./Doc";
+import { Doc, FieldResult, UpdatingFromServer, LayoutSym, AclPrivate, AclEdit, AclReadonly, AclAddonly, AclSym, CachedUpdates, DataSym, DocListCast, AclAdmin, FieldsSym, HeightSym, WidthSym, fetchProto } from "./Doc";
 import { SerializationHelper } from "../client/util/SerializationHelper";
 import { ProxyField, PrefetchProxy } from "./Proxy";
 import { RefField } from "./RefField";
@@ -183,12 +183,18 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc
         ["Admin", 4]
     ]);
 
+    let changed = false;
+
     const dataDoc = target[DataSym];
 
-    if (!inheritingFromCollection || !target[key] || HierarchyMapping.get(StrCast(target[key]))! > HierarchyMapping.get(acl)!) target[key] = acl;
+    if (!inheritingFromCollection || !target[key] || HierarchyMapping.get(StrCast(target[key]))! > HierarchyMapping.get(acl)!) {
+        target[key] = acl;
+        changed = true;
+    }
 
     if (dataDoc && (!inheritingFromCollection || !dataDoc[key] || HierarchyMapping.get(StrCast(dataDoc[key]))! > HierarchyMapping.get(acl)!)) {
         dataDoc[key] = acl;
+        changed = true;
 
         DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc)]).map(d => {
             if (d.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !d[key] || HierarchyMapping.get(StrCast(d[key]))! > HierarchyMapping.get(acl)!)) {
@@ -214,6 +220,8 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc
             }
         });
     }
+
+    changed && fetchProto(target);
 }
 
 const layoutProps = ["panX", "panY", "width", "height", "nativeWidth", "nativeHeight", "fitWidth", "fitToBox",
-- 
cgit v1.2.3-70-g09d2


From abb2140eb098b29e7b42b54d8e3173149c8a1123 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Thu, 30 Jul 2020 09:50:33 -0500
Subject: framework for ink in properties

---
 .../collectionFreeForm/FormatShapePane.tsx         |  2 +-
 .../collectionFreeForm/PropertiesView.scss         | 68 ++++++++++++++++++++++
 .../collectionFreeForm/PropertiesView.tsx          | 40 +++++++++++++
 3 files changed, 109 insertions(+), 1 deletion(-)

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

diff --git a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
index ddc282e57..eb6097acf 100644
--- a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
+++ b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
@@ -395,12 +395,12 @@ export default class FormatShapePane extends AntimodeMenu {
     @computed get widInput() { return this.inputBox("wid", this.shapeWid, (val: string) => this.shapeWid = val); }
     @computed get rotInput() { return this.inputBoxDuo("rot", this.shapeRot, (val: string) => { this.rotate(Number(val) - Number(this.shapeRot)); this.shapeRot = val; return true; }, "∠:", "rot", this.shapeRot, (val: string) => this.shapeRot = val, ""); }
 
-    @computed get XpsInput() { return this.inputBoxDuo("Xps", this.shapeXps, (val: string) => this.shapeXps = val, "X:", "Yps", this.shapeYps, (val: string) => this.shapeYps = val, "Y:"); }
     @computed get YpsInput() { return this.inputBox("Yps", this.shapeYps, (val: string) => this.shapeYps = val); }
 
     @computed get controlPoints() { return this.controlPointsButton(); }
     @computed get lockRatio() { return this.lockRatioButton(); }
     @computed get rotate90() { return this.rotate90Button(); }
+    @computed get XpsInput() { return this.inputBoxDuo("Xps", this.shapeXps, (val: string) => this.shapeXps = val, "X:", "Yps", this.shapeYps, (val: string) => this.shapeYps = val, "Y:"); }
 
 
     @computed get propertyGroupItems() {
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index cb4b7375b..f70e5f837 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -117,6 +117,74 @@
         }
     }
 
+    .propertiesView-appearance {
+        border-bottom: 1px solid black;
+        //padding: 8.5px;
+
+        .propertiesView-appearance-title {
+            font-weight: bold;
+            font-size: 12.5px;
+            padding: 4px;
+            display: flex;
+            width: 200px;
+            color: white;
+            padding-left: 8px;
+            background-color: rgb(51, 51, 51);
+
+            .propertiesView-appearance-title-icon {
+                float: right;
+                right: 0;
+                position: absolute;
+                margin-left: 2px;
+                margin-right: 9px;
+
+                &:hover {
+                    cursor: pointer;
+                }
+            }
+        }
+
+        .propertiesView-appearance-content {
+            font-size: 10px;
+            padding: 10px;
+            margin-left: 5px;
+        }
+    }
+
+    .propertiesView-transform {
+        border-bottom: 1px solid black;
+        //padding: 8.5px;
+
+        .propertiesView-transform-title {
+            font-weight: bold;
+            font-size: 12.5px;
+            padding: 4px;
+            display: flex;
+            width: 200px;
+            color: white;
+            padding-left: 8px;
+            background-color: rgb(51, 51, 51);
+
+            .propertiesView-transform-title-icon {
+                float: right;
+                right: 0;
+                position: absolute;
+                margin-left: 2px;
+                margin-right: 9px;
+
+                &:hover {
+                    cursor: pointer;
+                }
+            }
+        }
+
+        .propertiesView-transform-content {
+            font-size: 10px;
+            padding: 10px;
+            margin-left: 5px;
+        }
+    }
+
     .notify-button {
         padding: 2px;
         width: 12px;
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index d5317efcb..7c8e7cdc3 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -18,6 +18,8 @@ import { SelectionManager } from "../../../util/SelectionManager";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { Tooltip, Checkbox } from "@material-ui/core";
 import SharingManager from "../../../util/SharingManager";
+import { DocumentType } from "../../../documents/DocumentTypes";
+import FormatShapePane from "./FormatShapePane";
 
 
 interface PropertiesViewProps {
@@ -47,6 +49,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @observable openSharing: boolean = true;
     @observable openFields: boolean = true;
     @observable openLayout: boolean = true;
+    @observable openAppearance: boolean = true;
+    @observable openTransform: boolean = true;
+
+    @computed get isInk() { return this.selectedDoc?.type === DocumentType.INK; }
 
     @action
     rtfWidth = () => {
@@ -383,6 +389,40 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                     {this.sharingTable}
                 </div> : null}
             </div>
+
+
+
+
+            {this.isInk ? <div className="propertiesView-appearance">
+                <div className="propertiesView-appearance-title" style={{ backgroundColor: this.openAppearance ? "black" : "" }}>
+                    Appearance
+                    <div className="propertiesView-appearance-title-icon"
+                        onPointerDown={() => runInAction(() => { this.openAppearance = !this.openAppearance; })}>
+                        <FontAwesomeIcon icon={this.openAppearance ? "caret-down" : "caret-right"} size="lg" color="white" />
+                    </div>
+                </div>
+                {this.openAppearance ? <div className="propertiesView-appearance-content">
+                    <FormatShapePane />
+                </div> : null}
+            </div> : null}
+
+            {this.isInk ? <div className="propertiesView-transform">
+                <div className="propertiesView-transform-title" style={{ backgroundColor: this.openTransform ? "black" : "" }}>
+                    Transform
+                    <div className="propertiesView-transform-title-icon"
+                        onPointerDown={() => runInAction(() => { this.openTransform = !this.openTransform; })}>
+                        <FontAwesomeIcon icon={this.openTransform ? "caret-down" : "caret-right"} size="lg" color="white" />
+                    </div>
+                </div>
+                {this.openTransform ? <div className="propertiesView-transform-content">
+                    transform
+                </div> : null}
+            </div> : null}
+
+
+
+
+
             <div className="propertiesView-fields">
                 <div className="propertiesView-fields-title" style={{ backgroundColor: this.openFields ? "black" : "" }}>
                     <div className="propertiesView-fields-title-name">
-- 
cgit v1.2.3-70-g09d2


From a61c116e9028c2778b5c48cd596f9cb00d80d0f6 Mon Sep 17 00:00:00 2001
From: usodhi <61431818+usodhi@users.noreply.github.com>
Date: Thu, 30 Jul 2020 23:29:37 +0530
Subject: ui and other minor changes

---
 src/client/util/GroupMemberView.scss                      |  2 +-
 .../collections/collectionFreeForm/PropertiesView.scss    | 15 ++++++++++++---
 .../collections/collectionFreeForm/PropertiesView.tsx     | 14 +++++++-------
 3 files changed, 20 insertions(+), 11 deletions(-)

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

diff --git a/src/client/util/GroupMemberView.scss b/src/client/util/GroupMemberView.scss
index c609c5c7b..e8a4bc0c1 100644
--- a/src/client/util/GroupMemberView.scss
+++ b/src/client/util/GroupMemberView.scss
@@ -43,7 +43,7 @@
             text-overflow: ellipsis;
 
             &:hover {
-                text-overflow: visible;
+                text-overflow: unset;
                 overflow-x: auto;
             }
         }
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index 4ccc0950b..4917b7822 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -126,7 +126,7 @@
         padding-left: 2px;
         padding-right: 2px;
         margin-top: 2px;
-        margin-right: 3px;
+        margin-left: 3px;
 
         .notify-button-icon {
             width: 6px;
@@ -166,18 +166,25 @@
 
             display: flex;
             padding: 3px;
-
+            align-items: center;
             border-bottom: 0.5px solid grey;
 
+            &:hover .propertiesView-sharingTable-item-name {
+                overflow-x: unset;
+                white-space: unset;
+                overflow-wrap: break-word;
+            }
+
             .propertiesView-sharingTable-item-name {
                 font-weight: bold;
                 width: 80px;
                 overflow-x: hidden;
                 display: inline-block;
+                text-overflow: ellipsis;
+                white-space: nowrap;
             }
 
             .propertiesView-sharingTable-item-permission {
-
                 display: flex;
 
                 .permissions-select {
@@ -185,6 +192,8 @@
                     border: none;
                     background-color: inherit;
                     width: 75px;
+                    text-align: justify; // for Edge
+                    text-align-last: end;
 
                     &:hover {
                         cursor: pointer;
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index b33b37f4b..bd720ac82 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -263,7 +263,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
     @computed get notifyIcon() {
-        return <Tooltip title={<><div className="dash-tooltip">{"Notify group of permissions change"}</div></>}>
+        return <Tooltip title={<><div className="dash-tooltip">Notify with message</div></>}>
             <div className="notify-button">
                 <FontAwesomeIcon className="notify-button-icon" icon="bell" color="white" size="sm" />
             </div>
@@ -282,10 +282,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         </Tooltip>;
     }
 
-    sharingItem(name: string, notify: boolean, effectiveAcl: symbol, permission?: string) {
+    sharingItem(name: string, effectiveAcl: symbol, permission?: string) {
         return <div className="propertiesView-sharingTable-item">
-            <div className="propertiesView-sharingTable-item-name" style={{ width: notify ? "70px" : "80px" }}> {name} </div>
-            {notify ? this.notifyIcon : null}
+            <div className="propertiesView-sharingTable-item-name" style={{ width: name !== "Me" ? "70px" : "80px" }}> {name} </div>
+            {name !== "Me" ? this.notifyIcon : null}
             <div className="propertiesView-sharingTable-item-permission">
                 {effectiveAcl === AclAdmin && permission !== "Owner" ? this.getPermissionsSelect(name) : permission}
                 {permission === "Owner" ? this.expansionIcon : null}
@@ -308,12 +308,12 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         if (this.selectedDoc![AclSym]) {
             for (const [key, value] of Object.entries(this.selectedDoc![AclSym])) {
                 const name = key.substring(4).replace("_", ".");
-                if (name !== Doc.CurrentUserEmail && name !== this.selectedDoc!.author) tableEntries.push(this.sharingItem(name, false, effectiveAcl, AclMap.get(value)!));
+                if (name !== Doc.CurrentUserEmail && name !== this.selectedDoc!.author) tableEntries.push(this.sharingItem(name, effectiveAcl, AclMap.get(value)!));
             }
         }
 
-        tableEntries.unshift(this.sharingItem("Me", false, effectiveAcl, Doc.CurrentUserEmail === this.selectedDoc!.author ? "Owner" : StrCast(this.selectedDoc![`ACL-${Doc.CurrentUserEmail.replace(".", "_")}`])));
-        if (Doc.CurrentUserEmail !== this.selectedDoc!.author) tableEntries.unshift(this.sharingItem(StrCast(this.selectedDoc!.author), false, effectiveAcl, "Owner"));
+        tableEntries.unshift(this.sharingItem("Me", effectiveAcl, Doc.CurrentUserEmail === this.selectedDoc!.author ? "Owner" : StrCast(this.selectedDoc![`ACL-${Doc.CurrentUserEmail.replace(".", "_")}`])));
+        if (Doc.CurrentUserEmail !== this.selectedDoc!.author) tableEntries.unshift(this.sharingItem(StrCast(this.selectedDoc!.author), effectiveAcl, "Owner"));
 
         return <div className="propertiesView-sharingTable">
             {tableEntries}
-- 
cgit v1.2.3-70-g09d2


From 1ea51992bd418c319a253ed41c50497a6b13de25 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Thu, 30 Jul 2020 15:31:34 -0500
Subject: fixing layouts UI

---
 src/client/util/CurrentUserUtils.ts                |   6 +-
 src/client/views/MainView.scss                     |  49 +-----
 src/client/views/MainView.tsx                      | 173 ++++++++-------------
 .../collectionFreeForm/PropertiesView.scss         |  27 ++--
 .../collectionFreeForm/PropertiesView.tsx          |  14 +-
 5 files changed, 89 insertions(+), 180 deletions(-)

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

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 725be882e..3d8bd6bd5 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -508,12 +508,12 @@ export class CurrentUserUtils {
         return [
             { title: "Workspace", icon: "desktop", click: 'scriptContext.selectMenu("Workspace")' },
             { title: "Catalog", icon: "file", click: 'scriptContext.selectMenu("Catalog")' },
-            { title: "Archive", icon: "archive", click: 'scriptContext.selectMenu("deleted")' },
+            { title: "Archive", icon: "archive", click: 'scriptContext.selectMenu("Archive")' },
             { title: "Import", icon: "upload", click: 'scriptContext.selectMenu("Import")' },
-            { title: "Sharing", icon: "users", click: 'scriptContext.groupManager.open()' },
+            { title: "Sharing", icon: "users", click: 'scriptContext.selectMenu("Sharing")' },
             { title: "Tools", icon: "wrench", click: 'scriptContext.selectMenu("Tools")' },
             { title: "Help", icon: "question-circle", click: 'scriptContext.selectMenu("Help")' },
-            { title: "Settings", icon: "cog", click: 'SettingsManager.Instance.open()' },
+            { title: "Settings", icon: "cog", click: 'scriptContext.selectMenu("Settings")' },
         ];
     }
 
diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index fe01c27a3..054a409df 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -124,14 +124,13 @@
     }
 
     &:hover {
-        cursor: pointer;
+        cursor: grab;
     }
 }
 
 .mainiView-propertiesView {
     display: flex;
     flex-direction: column;
-    width: 200px;
     height: 100%;
     position: absolute;
     right: 0;
@@ -212,50 +211,6 @@
     }
 }
 
-// .mainView-menuPanel-bottomButton {
-//     width: 45px;
-//     height: 45px;
-//     padding: 10px;
-//     pointer-events: all;
-//     touch-action: none;
-//     //border-radius: inherit;
-//     background: black;
-//     background-color: black;
-//     //border-radius: 100%;
-//     transform-origin: top left;
-//     margin-bottom: 20px;
-//     margin-top: 5px;
-
-//     margin-right: 25px;
-
-//     .mainView-menuPanel-bottomButton-label {
-//         background: black;
-//         color: white;
-//         margin-left: -10px;
-//         border-radius: 8px;
-//         width: 65px;
-//         position: absolute;
-//         text-align: center;
-//         font-size: 9.5px;
-//         margin-top: 2px;
-//         letter-spacing: normal;
-//         padding: 3px;
-//         //margin-bottom: 23px;
-//     }
-
-//     .mainView-menuPanel-bottomButton-icon {
-//         width: 50px;
-//         height: 50px;
-//         color: white;
-//     }
-
-//     svg {
-//         width: 95% !important;
-//         height: 95%;
-//     }
-// }
-
-
 .mainView-searchPanel {
     width: 100%;
     height: 33px;
@@ -342,7 +297,7 @@
     position: absolute;
     z-index: 2;
     touch-action: none;
-    cursor: grab;
+    cursor: ew-resize;
 
     .mainView-libraryHandle-icon {
         width: 10px;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index ec0bff8a7..825a75afa 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -101,6 +101,7 @@ export class MainView extends React.Component {
             return "chevron-right";
         }
     }
+    @observable propertiesDownX: number | undefined;
 
     componentDidMount() {
         DocServer.setPlaygroundFields(["dataTransition", "_viewTransition", "_panX", "_panY", "_viewScale", "_viewType", "_chromeStatus"]); // can play with these fields on someone else's
@@ -233,7 +234,7 @@ export class MainView extends React.Component {
         const freeformOptions: DocumentOptions = {
             x: 0,
             y: 400,
-            _width: this._panelWidth * .7 - this._propertiesWidth,
+            _width: this._panelWidth * .7 - this.propertiesWidth(),
             _height: this._panelHeight,
             title: "Collection " + workspaceCount,
         };
@@ -299,12 +300,12 @@ export class MainView extends React.Component {
 
     @action
     onResize = (r: any) => {
-        this._panelWidth = r.offset.width - this._propertiesWidth;
+        this._panelWidth = r.offset.width - this.propertiesWidth();
         this._panelHeight = r.offset.height;
     }
 
     @action
-    getPWidth = () => this._panelWidth - this._propertiesWidth;
+    getPWidth = () => this._panelWidth - this.propertiesWidth();
 
     getPHeight = () => this._panelHeight;
     getContentsHeight = () => this._panelHeight - this._buttonBarHeight;
@@ -401,20 +402,67 @@ export class MainView extends React.Component {
         }
     }
 
+    @action
+    onDown = (e: React.PointerEvent) => {
+        this.propertiesDownX = e.screenX;
+        document.removeEventListener("pointermove", this.onPointerMove);
+        document.removeEventListener("pointerup", this.onPointerUp);
+        document.addEventListener("pointermove", this.onPointerMove);
+        document.addEventListener("pointerup", this.onPointerUp);
+        e.stopPropagation();
+        e.preventDefault();
+        // setupMoveUpEvents(this, e, action((e: PointerEvent, down: number[], delta: number[]) => {
+        //     this._propertiesWidth = this._panelWidth - Math.max(Transform.Identity().transformPoint(e.clientX, 0)[0], 0);
+        //     return false;
+        // }), returnFalse, action(() => this._propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this._panelWidth - 50, 200) : 0), false);
+    }
+
     @action
     onPointerMove = (e: PointerEvent) => {
-        this.flyoutWidth = Math.max(e.clientX, 0);
-        Math.abs(this.flyoutWidth - this._flyoutSizeOnDown) > 6 && (this._canClick = false);
-        this.sidebarButtonsDoc._columnWidth = this.flyoutWidth / 3 - 30;
+        if (this.propertiesDownX) {
+            this._propertiesWidth = this._propertiesWidth + (this.propertiesDownX - e.screenX) * .5;
+            if (this._propertiesWidth < 150) {
+                this._propertiesWidth = 0;
+                this.propertiesDownX = undefined;
+            } else if (this._propertiesWidth > 400) {
+                this._propertiesWidth = 400;
+                this.propertiesDownX = undefined;
+            }
+            document.removeEventListener("pointermove", this.onPointerMove);
+            document.removeEventListener("pointerup", this.onPointerUp);
+        } else {
+            this.flyoutWidth = Math.max(e.clientX, 0);
+            Math.abs(this.flyoutWidth - this._flyoutSizeOnDown) > 6 && (this._canClick = false);
+            this.sidebarButtonsDoc._columnWidth = this.flyoutWidth / 3 - 30;
+        }
     }
     @action
     onPointerUp = (e: PointerEvent) => {
-        if (Math.abs(e.clientX - this._flyoutSizeOnDown) < 4 && this._canClick) {
-            this.flyoutWidth = this.flyoutWidth < 15 ? 250 : 0;
-            this.flyoutWidth && (this.sidebarButtonsDoc._columnWidth = this.flyoutWidth / 3 - 30);
+        if (this.propertiesDownX) {
+            if (Math.abs(this.propertiesDownX - e.screenX) < 3) {
+                if (this._propertiesWidth < 10) {
+                    this._propertiesWidth = 200;
+                } else {
+                    this._propertiesWidth = 0;
+                }
+            } else {
+                this._propertiesWidth = this._propertiesWidth + (this.propertiesDownX - e.screenX) * .5;
+                if (this._propertiesWidth < 150) {
+                    this._propertiesWidth = 0;
+                } else if (this._propertiesWidth > 400) {
+                    this._propertiesWidth = 400;
+                }
+            }
+            this.propertiesDownX = undefined;
+        } else {
+            if (Math.abs(e.clientX - this._flyoutSizeOnDown) < 4 && this._canClick) {
+                this.flyoutWidth = this.flyoutWidth < 15 ? 250 : 0;
+                this.flyoutWidth && (this.sidebarButtonsDoc._columnWidth = this.flyoutWidth / 3 - 30);
+            }
         }
         document.removeEventListener("pointermove", this.onPointerMove);
         document.removeEventListener("pointerup", this.onPointerUp);
+
     }
     flyoutWidthFunc = () => this.flyoutWidth;
     addDocTabFunc = (doc: Doc, where: string, libraryPath?: Doc[]): boolean => {
@@ -501,91 +549,6 @@ export class MainView extends React.Component {
         </div>;
     }
 
-    // @computed get menuPanel() {
-    //     return <div className="mainView-menuPanel">
-    //         <div className="mainView-menuPanel-button" style={{ backgroundColor: this.panelContent === "workspace" ? "lightgrey" : "" }}>
-    //             <div className="mainView-menuPanel-button-wrap"
-    //                 style={{ backgroundColor: this.panelContent === "workspace" ? "lightgrey" : "" }}
-    //                 onPointerDown={e => this.selectPanel("workspace")}>
-    //                 <FontAwesomeIcon className="mainView-menuPanel-button-icon" icon="desktop"
-    //                     color={this.panelContent === "workspace" ? "black" : "white"} size="lg" />
-    //                 <div className="mainView-menuPanel-button-label"
-    //                     style={{ color: this.panelContent === "workspace" ? "black" : "white" }}> Workspace </div>
-    //             </div>
-    //         </div>
-
-    //         <div className="mainView-menuPanel-button" style={{ backgroundColor: this.panelContent === "catalog" ? "lightgrey" : "" }}>
-    //             <div className="mainView-menuPanel-button-wrap"
-    //                 style={{ backgroundColor: this.panelContent === "catalog" ? "lightgrey" : "" }}
-    //                 onPointerDown={e => this.selectPanel("catalog")}>
-    //                 <FontAwesomeIcon className="mainView-menuPanel-button-icon" icon="file"
-    //                     color={this.panelContent === "catalog" ? "black" : "white"} size="lg" />
-    //                 <div className="mainView-menuPanel-button-label"
-    //                     style={{ color: this.panelContent === "catalog" ? "black" : "white" }}> Catalog </div>
-    //             </div>
-    //         </div>
-
-    //         <div className="mainView-menuPanel-button" style={{ backgroundColor: this.panelContent === "deleted" ? "lightgrey" : "" }}>
-    //             <div className="mainView-menuPanel-button-wrap"
-    //                 style={{ backgroundColor: this.panelContent === "deleted" ? "lightgrey" : "" }}
-    //                 onPointerDown={e => this.selectPanel("deleted")}>
-    //                 <FontAwesomeIcon className="mainView-menuPanel-button-icon" icon="archive"
-    //                     color={this.panelContent === "deleted" ? "black" : "white"} size="lg" />
-    //                 <div className="mainView-menuPanel-button-label"
-    //                     style={{ color: this.panelContent === "deleted" ? "black" : "white" }}> Recently Used </div>
-    //             </div>
-    //         </div>
-
-    //         <div className="mainView-menuPanel-button">
-    //             <div className="mainView-menuPanel-button-wrap"
-    //                 onPointerDown={e => this.selectPanel("upload")}>
-    //                 <FontAwesomeIcon className="mainView-menuPanel-button-icon" icon="upload" color="white" size="lg" />
-    //                 <div className="mainView-menuPanel-button-label"> Import </div>
-    //             </div>
-    //         </div>
-
-    //         <div className="mainView-menuPanel-button">
-    //             <div className="mainView-menuPanel-button-wrap"
-    //                 //onPointerDown={e => this.selectPanel("sharing")}
-    //                 onClick={() => GroupManager.Instance.open()}>
-    //                 <FontAwesomeIcon className="mainView-menuPanel-button-icon" icon="users" color="white" size="lg" />
-    //                 <div className="mainView-menuPanel-button-label"> Sharing </div>
-    //             </div>
-    //         </div>
-
-    //         <div className="mainView-menuPanel-button" style={{ marginBottom: "110px", backgroundColor: this.panelContent === "tools" ? "lightgrey" : "", }}>
-    //             <div className="mainView-menuPanel-button-wrap"
-    //                 onPointerDown={e => this.selectPanel("tools")}
-    //                 style={{
-    //                     backgroundColor: this.panelContent === "tools" ? "lightgrey" : "",
-    //                 }}>
-    //                 <FontAwesomeIcon className="mainView-menuPanel-button-icon" icon="wrench"
-    //                     color={this.panelContent === "tools" ? "black" : "white"} size="lg" />
-    //                 <div className="mainView-menuPanel-button-label"
-    //                     style={{ color: this.panelContent === "tools" ? "black" : "white" }}> Tools </div>
-    //             </div>
-    //         </div>
-
-    //         <div className="mainView-menuPanel-button">
-    //             <div className="mainView-menuPanel-button-wrap"
-    //                 // style={{backgroundColor: this.panelContent= "help" ? "lightgrey" : "black"}}
-    //                 onPointerDown={e => this.selectPanel("help")} >
-    //                 <FontAwesomeIcon className="mainView-menuPanel-button-icon" icon="question-circle" color="white" size="lg" />
-    //                 <div className="mainView-menuPanel-button-label"> Help </div>
-    //             </div>
-    //         </div>
-
-    //         <div className="mainView-menuPanel-button">
-    //             <div className="mainView-menuPanel-button-wrap"
-    //                 // onPointerDown={e => this.selectPanel("settings")}
-    //                 onClick={() => SettingsManager.Instance.open()}>
-    //                 <FontAwesomeIcon className="mainView-menuPanel-button-icon" icon="cog" color="white" size="lg" />
-    //                 <div className="mainView-menuPanel-button-label"> Settings </div>
-    //             </div>
-    //         </div>
-    //     </div>;
-    // }
-
 
     @action @undoBatch
     closeFlyout = () => {
@@ -606,8 +569,9 @@ export class MainView extends React.Component {
                 case "Tools": this.sidebarContent.proto = CurrentUserUtils.toolsStack; break;
                 case "Workspace": this.sidebarContent.proto = CurrentUserUtils.workspaceStack; break;
                 case "Catalog": this.sidebarContent.proto = CurrentUserUtils.catalogStack; break;
-                case "deleted": this.sidebarContent.proto = CurrentUserUtils.closedStack; break;
-                case "Search": this.sidebarContent.proto = CurrentUserUtils.searchStack; break;
+                case "Archive": this.sidebarContent.proto = CurrentUserUtils.closedStack; break;
+                case "Settings": this.sidebarContent.proto = SettingsManager.Instance.open(); break;
+                case "Sharing": this.sidebarContent.proto = GroupManager.Instance.open(); break;
             }
             MainView.expandFlyout();
         }
@@ -615,25 +579,21 @@ export class MainView extends React.Component {
     }
 
     @action @undoBatch
-    onDown = (e: React.PointerEvent) => {
-        setupMoveUpEvents(this, e, action((e: PointerEvent, down: number[], delta: number[]) => {
-            this._propertiesWidth = this._panelWidth - Math.max(Transform.Identity().transformPoint(e.clientX, 0)[0], 0);
-            return false;
-        }), returnFalse, action(() => this._propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this._panelWidth - 50, 200) : 0), false);
+    closeProperties = () => {
+        this._propertiesWidth = 0;
     }
 
     @computed get propertiesView() {
         TraceMobx();
         return <div className="mainView-propertiesView" style={{
-            width: `200px`,
             overflow: this.propertiesWidth() < 15 ? "hidden" : undefined
         }}>
             <PropertiesView
-                width={200}
+                width={this.propertiesWidth()}
                 height={this._panelHeight}
                 renderDepth={1}
                 ScreenToLocalTransform={Transform.Identity}
-                onDown={this.onDown}
+                onDown={this.closeProperties}
             />
         </div>;
     }
@@ -643,7 +603,7 @@ export class MainView extends React.Component {
         const n = (CollectionMenu.Instance?.Pinned ? 1 : 0);
         const height = `calc(100% - ${n * Number(ANTIMODEMENU_HEIGHT.replace("px", ""))}px)`;
 
-        const rightFlyout = this.selectedDocumentView ? this._propertiesWidth - 1 : this.propertiesWidth() > 10 ? 151.5 : 0;
+        const rightFlyout = this.propertiesWidth() - 1;
         return !this.userDoc ? (null) : (
             <div className="mainView-mainContent" style={{
                 color: this.darkScheme ? "rgb(205,205,205)" : "black",
@@ -684,7 +644,8 @@ export class MainView extends React.Component {
                                 <FontAwesomeIcon icon={this.propertiesIcon} color="white" size="sm" /> </div>
                         </div>
                     }
-                    {this.propertiesWidth() < 10 ? (null) : this.propertiesView}
+                    {this.propertiesWidth() < 10 ? (null) :
+                        <div style={{ width: this.propertiesWidth() }}> {this.propertiesView} </div>}
                 </div>
             </div>);
     }
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index 83e0fc0d5..76c934551 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -57,7 +57,6 @@
             font-size: 12.5px;
             padding: 4px;
             display: flex;
-            width: 200px;
             color: white;
             padding-left: 8px;
             background-color: rgb(51, 51, 51);
@@ -92,7 +91,6 @@
             font-size: 12.5px;
             padding: 4px;
             display: flex;
-            width: 200px;
             color: white;
             padding-left: 8px;
             background-color: rgb(51, 51, 51);
@@ -126,7 +124,6 @@
             font-size: 12.5px;
             padding: 4px;
             display: flex;
-            width: 200px;
             color: white;
             padding-left: 8px;
             background-color: rgb(51, 51, 51);
@@ -160,7 +157,6 @@
             font-size: 12.5px;
             padding: 4px;
             display: flex;
-            width: 200px;
             color: white;
             padding-left: 8px;
             background-color: rgb(51, 51, 51);
@@ -275,7 +271,6 @@
             font-size: 12.5px;
             padding: 4px;
             display: flex;
-            width: 200px;
             color: white;
             padding-left: 8px;
             background-color: rgb(51, 51, 51);
@@ -299,18 +294,17 @@
                     cursor: pointer;
                 }
             }
+        }
 
-            .propertiesView-fields-title-checkbox {
-                float: right;
-                height: 20px;
-                margin-top: -13px;
-                margin-left: 115px;
-
-                .propertiesView-fields-title-checkbox-text {
-                    font-size: 7px;
-                    margin-top: -10px;
-                    margin-left: 6px;
-                }
+        .propertiesView-fields-checkbox {
+            float: right;
+            height: 20px;
+            margin-top: -9px;
+
+            .propertiesView-fields-checkbox-text {
+                font-size: 7px;
+                margin-top: -10px;
+                margin-left: 6px;
             }
         }
 
@@ -352,7 +346,6 @@
             font-size: 12.5px;
             padding: 4px;
             display: flex;
-            width: 200px;
             color: white;
             padding-left: 8px;
             background-color: rgb(51, 51, 51);
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index c4291f2a4..976e52fda 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -361,16 +361,16 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     render() {
 
         if (!this.selectedDoc) {
-            return <div className="propertiesView" >
-                <div className="propertiesView-title">
+            return <div className="propertiesView" style={{ width: this.props.width }}>
+                <div className="propertiesView-title" style={{ width: this.props.width, paddingLeft: 6 }}>
                     No Document Selected
             </div> </div>;
         }
 
         const novice = Doc.UserDoc().noviceMode;
 
-        return <div className="propertiesView" >
-            <div className="propertiesView-title">
+        return <div className="propertiesView" style={{ width: this.props.width }} >
+            <div className="propertiesView-title" style={{ width: this.props.width }}>
                 <div className="propertiesView-title-name">Properties </div>
                 <div className="propertiesView-title-icon" onPointerDown={this.props.onDown}>
                     <FontAwesomeIcon icon="times" color="black" size="sm" />
@@ -381,7 +381,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
             </div>
             <div className="propertiesView-settings">
                 <div className="propertiesView-settings-title" style={{ backgroundColor: this.openActions ? "black" : "" }}>
-                    Document Actions
+                    Actions
                     <div className="propertiesView-settings-title-icon"
                         onPointerDown={() => runInAction(() => { this.openActions = !this.openActions; })}>
                         <FontAwesomeIcon icon={this.openActions ? "caret-down" : "caret-right"} size="lg" color="white" />
@@ -447,9 +447,9 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                         </div>
                     </div>
                 </div>
-                {!novice && this.openFields ? <div className="propertiesView-fields-title-checkbox">
+                {!novice && this.openFields ? <div className="propertiesView-fields-checkbox">
                     {this.fieldsCheckbox}
-                    <div className="propertiesView-fields-title-checkbox-text">Layout</div>
+                    <div className="propertiesView-fields-checkbox-text">Layout</div>
                 </div> : null}
                 {this.openFields ?
                     <div className="propertiesView-fields-content">
-- 
cgit v1.2.3-70-g09d2


From 57122492fc344d254c507422aace7932b785276c Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Thu, 30 Jul 2020 19:46:55 -0500
Subject: started merging with ink, transform buttons done

---
 src/client/documents/Documents.ts                  |   8 +-
 src/client/views/MainView.tsx                      |   2 +-
 .../collectionFreeForm/PropertiesView.scss         |  55 ++++++++++
 .../collectionFreeForm/PropertiesView.tsx          | 118 ++++++++++++++++++++-
 4 files changed, 175 insertions(+), 8 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 32f46bd1c..88c25567e 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -304,10 +304,10 @@ export namespace Docs {
             [DocumentType.MENUICON, {
                 layout: { view: MenuIconBox, dataField: defaultDataKey },
             }],
-            [DocumentType.RECOMMENDATION, {
-                layout: { view: RecommendationsBox, dataField: defaultDataKey },
-                options: { _width: 200, _height: 200 },
-            }],
+            // [DocumentType.RECOMMENDATION, {
+            //     layout: { view: RecommendationsBox, dataField: defaultDataKey },
+            //     options: { _width: 200, _height: 200 },
+            // }],
             [DocumentType.WEBCAM, {
                 layout: { view: DashWebRTCVideo, dataField: defaultDataKey }
             }],
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 0e2362866..8e4851b6e 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -172,7 +172,7 @@ export class MainView extends React.Component {
             fa.faFillDrip, fa.faLink, fa.faUnlink, fa.faBold, fa.faItalic, fa.faChevronLeft, fa.faUnderline, fa.faStrikethrough, fa.faSuperscript, fa.faSubscript,
             fa.faIndent, fa.faEyeDropper, fa.faPaintRoller, fa.faBars, fa.faBrush, fa.faShapes, fa.faEllipsisH, fa.faHandPaper, fa.faMap, fa.faUser, faHireAHelper,
             fa.faDesktop, fa.faTrashRestore, fa.faUsers, fa.faWrench, fa.faCog, fa.faMap, fa.faBellSlash, fa.faExpandAlt, fa.faArchive, fa.faBezierCurve, fa.faCircle,
-            fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, faBuffer, fa.faExpand);
+            fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, faBuffer, fa.faExpand, fa.faUndo);
         this.initEventListeners();
         this.initAuthenticationRouters();
     }
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index 30598adfb..f44445066 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -378,4 +378,59 @@
         }
 
     }
+}
+
+.inking-button {
+
+    display: flex;
+
+    .inking-button-points {
+        background-color: #333333;
+        padding: 7px;
+        border-radius: 7px;
+        margin-right: 32px;
+        width: 32;
+        height: 32;
+        padding-top: 9px;
+        margin-left: 5px;
+
+        &:hover {
+            background: rgb(131, 131, 131);
+            transform: scale(1.05);
+            cursor: pointer;
+        }
+    }
+
+    .inking-button-lock {
+        background-color: #333333;
+        padding: 7px;
+        border-radius: 7px;
+        margin-right: 32px;
+        width: 32;
+        height: 32;
+        padding-top: 9px;
+        padding-left: 10px;
+
+        &:hover {
+            background: rgb(131, 131, 131);
+            transform: scale(1.05);
+            cursor: pointer;
+        }
+    }
+
+    .inking-button-rotate {
+        background-color: #333333;
+        padding: 7px;
+        border-radius: 7px;
+        width: 32;
+        height: 32;
+        padding-top: 9px;
+        padding-left: 10px;
+
+        &:hover {
+            background: rgb(131, 131, 131);
+            transform: scale(1.05);
+            cursor: pointer;
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 57f31ca3d..90a55ed2d 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -2,7 +2,7 @@ import React = require("react");
 import { observer } from "mobx-react";
 import "./PropertiesView.scss";
 import { observable, action, computed, runInAction } from "mobx";
-import { Doc, Field, DocListCast, WidthSym, HeightSym, AclSym, AclPrivate, AclReadonly, AclAddonly, AclEdit, AclAdmin } from "../../../../fields/Doc";
+import { Doc, Field, DocListCast, WidthSym, HeightSym, AclSym, AclPrivate, AclReadonly, AclAddonly, AclEdit, AclAdmin, Opt } from "../../../../fields/Doc";
 import { DocumentView } from "../../nodes/DocumentView";
 import { ComputedField } from "../../../../fields/ScriptField";
 import { EditableView } from "../../EditableView";
@@ -21,6 +21,11 @@ import SharingManager from "../../../util/SharingManager";
 import { DocumentType } from "../../../documents/DocumentTypes";
 import FormatShapePane from "./FormatShapePane";
 import { SharingPermissions, GetEffectiveAcl } from "../../../../fields/util";
+import { InkField } from "../../../../fields/InkField";
+import { undoBatch } from "../../../util/UndoManager";
+import { ColorState, SketchPicker } from "react-color";
+import AntimodeMenu from "../../AntimodeMenu";
+import "./FormatShapePane.scss";
 
 
 interface PropertiesViewProps {
@@ -349,6 +354,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
             SetValue={this.setTitle} />;
     }
 
+    @action
     setTitle = (value: string) => {
         if (this.dataDoc) {
             this.selectedDoc && (this.selectedDoc.title = value);
@@ -358,6 +364,112 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         return false;
     }
 
+
+
+
+
+    @undoBatch
+    @action
+    rotate = (angle: number) => {
+        const _centerPoints: { X: number, Y: number }[] = [];
+        if (this.selectedDoc) {
+            const doc = this.selectedDoc;
+            if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) {
+                const ink = Cast(doc.data, InkField)?.inkData;
+                if (ink) {
+                    const xs = ink.map(p => p.X);
+                    const ys = ink.map(p => p.Y);
+                    const left = Math.min(...xs);
+                    const top = Math.min(...ys);
+                    const right = Math.max(...xs);
+                    const bottom = Math.max(...ys);
+                    _centerPoints.push({ X: left, Y: top });
+                }
+            }
+
+            var index = 0;
+            if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) {
+                doc.rotation = Number(doc.rotation) + Number(angle);
+                const ink = Cast(doc.data, InkField)?.inkData;
+                if (ink) {
+
+                    const newPoints: { X: number, Y: number }[] = [];
+                    for (var i = 0; i < ink.length; i++) {
+                        const newX = Math.cos(angle) * (ink[i].X - _centerPoints[index].X) - Math.sin(angle) * (ink[i].Y - _centerPoints[index].Y) + _centerPoints[index].X;
+                        const newY = Math.sin(angle) * (ink[i].X - _centerPoints[index].X) + Math.cos(angle) * (ink[i].Y - _centerPoints[index].Y) + _centerPoints[index].Y;
+                        newPoints.push({ X: newX, Y: newY });
+                    }
+                    doc.data = new InkField(newPoints);
+                    const xs = newPoints.map(p => p.X);
+                    const ys = newPoints.map(p => p.Y);
+                    const left = Math.min(...xs);
+                    const top = Math.min(...ys);
+                    const right = Math.max(...xs);
+                    const bottom = Math.max(...ys);
+
+                    doc._height = (bottom - top);
+                    doc._width = (right - left);
+                }
+                index++;
+            }
+        }
+    }
+
+    @observable _controlBtn: boolean = false;
+    @observable _lock: boolean = false;
+
+    @computed
+    get controlPointsButton() {
+        return <div className="inking-button">
+            <Tooltip title={<><div className="dash-tooltip">{"Edit points"}</div></>}>
+                <div className="inking-button-points" onPointerDown={action(() => this._controlBtn = !this._controlBtn)} style={{ backgroundColor: this._controlBtn ? "black" : "" }}>
+                    <FontAwesomeIcon icon="bezier-curve" color="white" size="lg" />
+                </div>
+            </Tooltip>
+            <Tooltip title={<><div className="dash-tooltip">{this._lock ? "Unlock points" : "Lock points"}</div></>}>
+                <div className="inking-button-lock" onPointerDown={action(() => this._lock = !this._lock)} >
+                    <FontAwesomeIcon icon={this._lock ? "unlock" : "lock"} color="white" size="lg" />
+                </div>
+            </Tooltip>
+            <Tooltip title={<><div className="dash-tooltip">{"Rotate 90˚"}</div></>}>
+                <div className="inking-button-rotate" onPointerDown={action(() => this.rotate(Math.PI / 2))}>
+                    <FontAwesomeIcon icon="undo" color="white" size="lg" />
+                </div>
+            </Tooltip>
+        </div>;
+    }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    @computed get appearanceEditor() { return "appearance" };
+
+    @computed get transformEditor() { return this.controlPointsButton };
+
     render() {
 
         if (!this.selectedDoc) {
@@ -416,7 +528,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                     </div>
                 </div>
                 {this.openAppearance ? <div className="propertiesView-appearance-content">
-                    <FormatShapePane />
+                    {this.appearanceEditor}
                 </div> : null}
             </div> : null}
 
@@ -429,7 +541,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                     </div>
                 </div>
                 {this.openTransform ? <div className="propertiesView-transform-content">
-                    transform
+                    {this.transformEditor}
                 </div> : null}
             </div> : null}
 
-- 
cgit v1.2.3-70-g09d2


From 7778393f3d920623f4281fa08eec6c4d8f9d3cf3 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Fri, 31 Jul 2020 12:17:35 -0500
Subject: transform in ink properties done

---
 src/client/views/collections/CollectionMenu.tsx    |   4 +-
 .../collectionFreeForm/PropertiesView.scss         |  64 ++++++++
 .../collectionFreeForm/PropertiesView.tsx          | 182 +++++++++++++++++----
 3 files changed, 215 insertions(+), 35 deletions(-)

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

diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 1ac8798bd..e70a16da9 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -332,11 +332,11 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
                         {this.props.type === CollectionViewType.Invalid ||
                             this.props.type === CollectionViewType.Docking || this.isText ? (null) : this.viewModes}
                         {this.props.type === CollectionViewType.Docking || this.isText ? (null) : this.templateChrome}
-                        <div className="collectionViewBaseChrome-viewSpecs" title="filter documents to show" style={{ display: "grid" }}>
+                        {/* <div className="collectionViewBaseChrome-viewSpecs" title="filter documents to show" style={{ display: "grid" }}>
                             <button className={"antimodeMenu-button"} onClick={this.toggleViewSpecs} >
                                 <FontAwesomeIcon icon="filter" size="lg" />
                             </button>
-                        </div>
+                        </div> */}
 
                         {this.props.docView.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Freeform ? (null) : <button className={"antimodeMenu-button"} key="float"
                             style={{ backgroundColor: !this.props.docView.layoutDoc.isAnnotating ? "121212" : undefined, borderRight: "1px solid gray" }}
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index f44445066..4cbf02107 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -433,4 +433,68 @@
             cursor: pointer;
         }
     }
+}
+
+.inputBox-duo {
+    display: flex;
+}
+
+.inputBox {
+
+    margin-top: 10px;
+    display: flex;
+    height: 19px;
+    margin-right: 15px;
+
+    .inputBox-title {
+        font-size: 12px;
+        padding-right: 5px;
+    }
+
+    .inputBox-input {
+        font-size: 10px;
+        width: 50px;
+        margin-right: 1px;
+        border-radius: 3px;
+
+        &:hover {
+            cursor: pointer;
+        }
+    }
+
+    .inputBox-button {
+
+        .inputBox-button-up {
+            background-color: #333333;
+    height: 9px;
+    padding-left: 3px;
+    padding-right: 3px;
+    padding-top: 1px;
+    padding-bottom: 1px;
+    border-radius: 1.5px;
+
+            &:hover {
+                background: rgb(131, 131, 131);
+                transform: scale(1.05);
+                cursor: pointer;
+            }
+        }
+
+        .inputBox-button-down {
+            background-color: #333333;
+    height: 9px;
+    padding-left: 3px;
+    padding-right: 3px;
+    padding-top: 1px;
+    padding-bottom: 1px;
+    border-radius: 1.5px;
+
+            &:hover {
+                background: rgb(131, 131, 131);
+                transform: scale(1.05);
+                cursor: pointer;
+            }
+        }
+
+    }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 90a55ed2d..24521a6f2 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -368,6 +368,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
 
 
+
+
+
+
     @undoBatch
     @action
     rotate = (angle: number) => {
@@ -439,27 +443,125 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         </div>;
     }
 
+    inputBox = (key: string, value: any, setter: (val: string) => {}, title: string) => {
+        return <div className="inputBox"
+            style={{
+                marginRight: title === "X:" ? "19px" : "",
+                marginLeft: title === "∠:" ? "39px" : ""
+            }}>
+            <div className="inputBox-title"> {title} </div>
+            <input className="inputBox-input"
+                type="text" value={value}
+                onChange={e => setter(e.target.value)} />
+            <div className="inputBox-button">
+                <div className="inputBox-button-up" key="up2"
+                    onPointerDown={undoBatch(action(() => this.upDownButtons("up", key)))} >
+                    <FontAwesomeIcon icon="caret-up" color="white" size="sm" />
+                </div>
+                <div className="inputbox-Button-down" key="down2"
+                    onPointerDown={undoBatch(action(() => this.upDownButtons("down", key)))} >
+                    <FontAwesomeIcon icon="caret-down" color="white" size="sm" />
+                </div>
+            </div>
+        </div>;
+    }
 
+    inputBoxDuo = (key: string, value: any, setter: (val: string) => {}, title1: string, key2: string, value2: any, setter2: (val: string) => {}, title2: string) => {
+        return <div className="inputBox-duo">
+            {this.inputBox(key, value, setter, title1)}
+            {title2 === "" ? (null) : this.inputBox(key2, value2, setter2, title2)}
+        </div>;
+    }
 
+    @action
+    upDownButtons = (dirs: string, field: string) => {
+        switch (field) {
+            case "rot": this.rotate((dirs === "up" ? .1 : -.1)); break;
+            // case "rot": this.selectedInk?.forEach(i => i.rootDoc.rotation = NumCast(i.rootDoc.rotation) + (dirs === "up" ? 0.1 : -0.1)); break;
+            case "Xps": this.selectedDoc && (this.selectedDoc.x = NumCast(this.selectedDoc?.x) + (dirs === "up" ? 10 : -10)); break;
+            case "Yps": this.selectedDoc && (this.selectedDoc.y = NumCast(this.selectedDoc?.y) + (dirs === "up" ? 10 : -10)); break;
+            case "stk": this.selectedDoc && (this.selectedDoc.strokeWidth = NumCast(this.selectedDoc?.strokeWidth) + (dirs === "up" ? .1 : -.1)); break;
+            case "wid":
+                const oldWidth = NumCast(this.selectedDoc?._width);
+                const oldHeight = NumCast(this.selectedDoc?._height);
+                const oldX = NumCast(this.selectedDoc?.x);
+                const oldY = NumCast(this.selectedDoc?.y);
+                this.selectedDoc && (this.selectedDoc._width = oldWidth + (dirs === "up" ? 10 : - 10));
+                this._lock && this.selectedDoc && (this.selectedDoc._height = (NumCast(this.selectedDoc?._width) / oldWidth * NumCast(this.selectedDoc?._height)));
+                const doc = this.selectedDoc;
+                if (doc?.type === DocumentType.INK && doc.x && doc.y && doc._height && doc._width) {
+                    console.log(doc.x, doc.y, doc._height, doc._width);
+                    const ink = Cast(doc.data, InkField)?.inkData;
+                    console.log(ink);
+                    if (ink) {
+                        const newPoints: { X: number, Y: number }[] = [];
+                        for (var j = 0; j < ink.length; j++) {
+                            // (new x — oldx) + (oldxpoint * newWidt)/oldWidth 
+                            const newX = (NumCast(doc.x) - oldX) + (ink[j].X * NumCast(doc._width)) / oldWidth;
+                            const newY = (NumCast(doc.y) - oldY) + (ink[j].Y * NumCast(doc._height)) / oldHeight;
+                            newPoints.push({ X: newX, Y: newY });
+                        }
+                        doc.data = new InkField(newPoints);
+                    }
+                }
+                break;
+            case "hgt":
+                const oWidth = NumCast(this.selectedDoc?._width);
+                const oHeight = NumCast(this.selectedDoc?._height);
+                const oX = NumCast(this.selectedDoc?.x);
+                const oY = NumCast(this.selectedDoc?.y);
+                this.selectedDoc && (this.selectedDoc._height = oHeight + (dirs === "up" ? 10 : - 10));
+                this._lock && this.selectedDoc && (this.selectedDoc._width = (NumCast(this.selectedDoc?._height) / oHeight * NumCast(this.selectedDoc?._width)));
+                const docu = this.selectedDoc;
+                if (docu?.type === DocumentType.INK && docu.x && docu.y && docu._height && docu._width) {
+                    console.log(docu.x, docu.y, docu._height, docu._width);
+                    const ink = Cast(docu.data, InkField)?.inkData;
+                    console.log(ink);
+                    if (ink) {
+                        const newPoints: { X: number, Y: number }[] = [];
+                        for (var j = 0; j < ink.length; j++) {
+                            // (new x — oldx) + (oldxpoint * newWidt)/oldWidth 
+                            const newX = (NumCast(docu.x) - oX) + (ink[j].X * NumCast(docu._width)) / oWidth;
+                            const newY = (NumCast(docu.y) - oY) + (ink[j].Y * NumCast(docu._height)) / oHeight;
+                            newPoints.push({ X: newX, Y: newY });
+                        }
+                        docu.data = new InkField(newPoints);
+                    }
+                }
+                break;
+        }
+    }
 
+    getField(key: string) {
+        //if (this.selectedDoc) {
+        return Field.toString(this.selectedDoc[key] as Field);
+        // } else {
+        //     return undefined as Opt<string>;
+        // }
+    }
 
+    @computed get shapeXps() { return this.getField("x"); }
+    @computed get shapeYps() { return this.getField("y"); }
+    @computed get shapeRot() { return this.getField("rotation"); }
+    @computed get shapeHgt() { return this.getField("_height"); }
+    @computed get shapeWid() { return this.getField("_width"); }
+    set shapeXps(value) { this.selectedDoc && (this.selectedDoc.x = Number(value)); }
+    set shapeYps(value) { this.selectedDoc && (this.selectedDoc.y = Number(value)); }
+    set shapeRot(value) { this.selectedDoc && (this.selectedDoc.rotation = Number(value)); }
+    set shapeWid(value) {
+        const oldWidth = NumCast(this.selectedDoc?._width);
+        this.selectedDoc && (this.selectedDoc._width = Number(value));
+        this._lock && this.selectedDoc && (this.selectedDoc._height = (NumCast(this.selectedDoc?._width) * NumCast(this.selectedDoc?._height)) / oldWidth);
+    }
+    set shapeHgt(value) {
+        const oldHeight = NumCast(this.selectedDoc?._height);
+        this.selectedDoc && (this.selectedDoc._height = Number(value));
+        this._lock && this.selectedDoc && (this.selectedDoc._width = (NumCast(this.selectedDoc?._height) * NumCast(this.selectedDoc?._width)) / oldHeight);
+    }
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+    @computed get hgtInput() { return this.inputBoxDuo("hgt", this.shapeHgt, (val: string) => this.shapeHgt = val, "H:", "wid", this.shapeWid, (val: string) => this.shapeWid = val, "W:"); }
+    @computed get XpsInput() { return this.inputBoxDuo("Xps", this.shapeXps, (val: string) => this.shapeXps = val, "X:", "Yps", this.shapeYps, (val: string) => this.shapeYps = val, "Y:"); }
+    @computed get rotInput() { return this.inputBoxDuo("rot", this.shapeRot, (val: string) => { this.rotate(Number(val) - Number(this.shapeRot)); this.shapeRot = val; return true; }, "∠:", "rot", this.shapeRot, (val: string) => this.shapeRot = val, ""); }
 
 
 
@@ -468,7 +570,14 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     @computed get appearanceEditor() { return "appearance" };
 
-    @computed get transformEditor() { return this.controlPointsButton };
+    @computed get transformEditor() {
+        return <div className="transform-editor">
+            {this.controlPointsButton}
+            {this.hgtInput}
+            {this.XpsInput}
+            {this.rotInput}
+        </div>;
+    };
 
     render() {
 
@@ -492,10 +601,11 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 {this.editableTitle}
             </div>
             <div className="propertiesView-settings">
-                <div className="propertiesView-settings-title" style={{ backgroundColor: this.openActions ? "black" : "" }}>
+                <div className="propertiesView-settings-title"
+                    onPointerDown={() => runInAction(() => { this.openActions = !this.openActions; })}
+                    style={{ backgroundColor: this.openActions ? "black" : "" }}>
                     Actions
-                    <div className="propertiesView-settings-title-icon"
-                        onPointerDown={() => runInAction(() => { this.openActions = !this.openActions; })}>
+                    <div className="propertiesView-settings-title-icon">
                         <FontAwesomeIcon icon={this.openActions ? "caret-down" : "caret-right"} size="lg" color="white" />
                     </div>
                 </div>
@@ -504,10 +614,11 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 </div> : null}
             </div>
             <div className="propertiesView-sharing">
-                <div className="propertiesView-sharing-title" style={{ backgroundColor: this.openSharing ? "black" : "" }}>
+                <div className="propertiesView-sharing-title"
+                    onPointerDown={() => runInAction(() => { this.openSharing = !this.openSharing; })}
+                    style={{ backgroundColor: this.openSharing ? "black" : "" }}>
                     Sharing {"&"} Permissions
-                    <div className="propertiesView-sharing-title-icon"
-                        onPointerDown={() => runInAction(() => { this.openSharing = !this.openSharing; })}>
+                    <div className="propertiesView-sharing-title-icon">
                         <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="white" />
                     </div>
                 </div>
@@ -520,10 +631,11 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
 
             {this.isInk ? <div className="propertiesView-appearance">
-                <div className="propertiesView-appearance-title" style={{ backgroundColor: this.openAppearance ? "black" : "" }}>
+                <div className="propertiesView-appearance-title"
+                    onPointerDown={() => runInAction(() => { this.openAppearance = !this.openAppearance; })}
+                    style={{ backgroundColor: this.openAppearance ? "black" : "" }}>
                     Appearance
-                    <div className="propertiesView-appearance-title-icon"
-                        onPointerDown={() => runInAction(() => { this.openAppearance = !this.openAppearance; })}>
+                    <div className="propertiesView-appearance-title-icon">
                         <FontAwesomeIcon icon={this.openAppearance ? "caret-down" : "caret-right"} size="lg" color="white" />
                     </div>
                 </div>
@@ -533,10 +645,11 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
             </div> : null}
 
             {this.isInk ? <div className="propertiesView-transform">
-                <div className="propertiesView-transform-title" style={{ backgroundColor: this.openTransform ? "black" : "" }}>
+                <div className="propertiesView-transform-title"
+                    onPointerDown={() => runInAction(() => { this.openTransform = !this.openTransform; })}
+                    style={{ backgroundColor: this.openTransform ? "black" : "" }}>
                     Transform
-                    <div className="propertiesView-transform-title-icon"
-                        onPointerDown={() => runInAction(() => { this.openTransform = !this.openTransform; })}>
+                    <div className="propertiesView-transform-title-icon">
                         <FontAwesomeIcon icon={this.openTransform ? "caret-down" : "caret-right"} size="lg" color="white" />
                     </div>
                 </div>
@@ -550,11 +663,12 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
 
             <div className="propertiesView-fields">
-                <div className="propertiesView-fields-title" style={{ backgroundColor: this.openFields ? "black" : "" }}>
+                <div className="propertiesView-fields-title"
+                    onPointerDown={() => runInAction(() => { this.openFields = !this.openFields; })}
+                    style={{ backgroundColor: this.openFields ? "black" : "" }}>
                     <div className="propertiesView-fields-title-name">
                         Fields {"&"} Tags
-                        <div className="propertiesView-fields-title-icon"
-                            onPointerDown={() => runInAction(() => { this.openFields = !this.openFields; })}>
+                        <div className="propertiesView-fields-title-icon">
                             <FontAwesomeIcon icon={this.openFields ? "caret-down" : "caret-right"} size="lg" color="white" />
                         </div>
                     </div>
@@ -569,7 +683,9 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                     </div> : null}
             </div>
             <div className="propertiesView-layout">
-                <div className="propertiesView-layout-title" style={{ backgroundColor: this.openLayout ? "black" : "" }}>
+                <div className="propertiesView-layout-title"
+                    onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}
+                    style={{ backgroundColor: this.openLayout ? "black" : "" }}>
                     Layout
                     <div className="propertiesView-layout-title-icon"
                         onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}>
-- 
cgit v1.2.3-70-g09d2


From 3504f35028dcd7df3cd65e8fdfa53e6b6876e09a Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Fri, 31 Jul 2020 14:56:30 -0500
Subject: starting appearance

---
 .../collectionFreeForm/PropertiesView.scss         |  65 ++++++++--
 .../collectionFreeForm/PropertiesView.tsx          | 142 ++++++++++++++++++++-
 2 files changed, 192 insertions(+), 15 deletions(-)

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

diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index 4cbf02107..0b23d2325 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -466,12 +466,12 @@
 
         .inputBox-button-up {
             background-color: #333333;
-    height: 9px;
-    padding-left: 3px;
-    padding-right: 3px;
-    padding-top: 1px;
-    padding-bottom: 1px;
-    border-radius: 1.5px;
+            height: 9px;
+            padding-left: 3px;
+            padding-right: 3px;
+            padding-top: 1px;
+            padding-bottom: 1px;
+            border-radius: 1.5px;
 
             &:hover {
                 background: rgb(131, 131, 131);
@@ -482,12 +482,12 @@
 
         .inputBox-button-down {
             background-color: #333333;
-    height: 9px;
-    padding-left: 3px;
-    padding-right: 3px;
-    padding-top: 1px;
-    padding-bottom: 1px;
-    border-radius: 1.5px;
+            height: 9px;
+            padding-left: 3px;
+            padding-right: 3px;
+            padding-top: 1px;
+            padding-bottom: 1px;
+            border-radius: 1.5px;
 
             &:hover {
                 background: rgb(131, 131, 131);
@@ -497,4 +497,45 @@
         }
 
     }
+}
+
+.color-palette {
+    width: 160px;
+    height: 360;
+}
+
+.strokeAndFill {
+
+    display: flex;
+
+    .fill {
+        margin-right: 30px;
+        display: flex;
+        padding-bottom: 7px;
+        margin-left: 20px;
+
+        .fill-title {
+            font-size: 12px;
+            margin-right: 2px;
+        }
+
+        .fill-button {
+            padding-top: 2px;
+            margin-top: -1px;
+        }
+    }
+
+    .stroke {
+        display: flex;
+
+        .stroke-title {
+            font-size: 12px;
+        }
+
+        .stroke-button {
+            padding-top: 2px;
+            margin-left: 2px;
+            margin-top: -1px;
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 24521a6f2..013b4be34 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -16,7 +16,7 @@ import { Transform } from "../../../util/Transform";
 import { PropertiesButtons } from "../../PropertiesButtons";
 import { SelectionManager } from "../../../util/SelectionManager";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { Tooltip, Checkbox } from "@material-ui/core";
+import { Tooltip, Checkbox, Divider } from "@material-ui/core";
 import SharingManager from "../../../util/SharingManager";
 import { DocumentType } from "../../../documents/DocumentTypes";
 import FormatShapePane from "./FormatShapePane";
@@ -563,12 +563,148 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @computed get XpsInput() { return this.inputBoxDuo("Xps", this.shapeXps, (val: string) => this.shapeXps = val, "X:", "Yps", this.shapeYps, (val: string) => this.shapeYps = val, "Y:"); }
     @computed get rotInput() { return this.inputBoxDuo("rot", this.shapeRot, (val: string) => { this.rotate(Number(val) - Number(this.shapeRot)); this.shapeRot = val; return true; }, "∠:", "rot", this.shapeRot, (val: string) => this.shapeRot = val, ""); }
 
+    @observable private _fillBtn = false;
+    @observable private _lineBtn = false;
+
+    private _lastFill = "#D0021B";
+    private _lastLine = "#D0021B";
+    private _lastDash = "2";
+
+    @computed get colorFil() { const ccol = this.getField("fillColor") || ""; ccol && (this._lastFill = ccol); return ccol; }
+    @computed get colorStk() { const ccol = this.getField("color") || ""; ccol && (this._lastLine = ccol); return ccol; }
+    set colorFil(value) { value && (this._lastFill = value); this.selectedDoc && (this.selectedDoc.fillColor = value ? value : undefined); }
+    set colorStk(value) { value && (this._lastLine = value); this.selectedDoc && (this.selectedDoc.color = value ? value : undefined); }
+
+    colorButton(value: string, setter: () => {}) {
+        return <div className="color-button" key="color" onPointerDown={undoBatch(action(e => setter()))}>
+            <div className="color-button-preview" style={{
+                backgroundColor: value ?? "121212", width: 15, height: 15,
+                display: value === "" || value === "transparent" ? "none" : ""
+            }} />
+            {value === "" || value === "transparent" ? <p style={{ fontSize: 25, color: "red", marginTop: -14, position: "fixed" }}>☒</p> : ""}
+        </div>;
+    }
+
+    @undoBatch
+    @action
+    switchStk = (color: ColorState) => {
+        const val = String(color.hex);
+        this.colorStk = val;
+        return true;
+    }
+    @undoBatch
+    @action
+    switchFil = (color: ColorState) => {
+        const val = String(color.hex);
+        this.colorFil = val;
+        return true;
+    }
+
+    colorPicker(setter: (color: string) => {}, type: string) {
+        return <SketchPicker onChange={type === "stk" ? this.switchStk : this.switchFil}
+            presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505',
+                '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B',
+                '#FFFFFF', '#f1efeb', 'transparent']}
+            color={type === "stk" ? this.colorStk : this.colorFil} />;
+    }
+
+    @computed get fillButton() { return this.colorButton(this.colorFil, () => { this._fillBtn = !this._fillBtn; this._lineBtn = false; return true; }); }
+    @computed get lineButton() { return this.colorButton(this.colorStk, () => { this._lineBtn = !this._lineBtn; this._fillBtn = false; return true; }); }
+
+    @computed get fillPicker() { return this.colorPicker((color: string) => this.colorFil = color, "fil"); }
+    @computed get linePicker() { return this.colorPicker((color: string) => this.colorStk = color, "stk"); }
+
+    @computed get strokeAndFill() {
+        return <div>
+            <div key="fill" className="strokeAndFill">
+                <div className="fill">
+                    <div className="fill-title">Fill:</div>
+                    <div className="fill-button">{this.fillButton}</div>
+                </div>
+                <div className="stroke">
+                    <div className="stroke-title"> Stroke: </div>
+                    <div className="stroke-button">{this.lineButton}</div>
+                </div>
+            </div>
+            {this._fillBtn ? this.fillPicker : ""}
+            {this._lineBtn ? this.linePicker : ""}
+        </div>;
+    }
+
+    @computed get solidStk() { return this.selectedDoc?.color && (!this.selectedDoc?.strokeDash || this.selectedDoc?.strokeDash === "0") ? true : false; }
+    @computed get dashdStk() { return !this.unStrokd && this.getField("strokeDash") || ""; }
+    @computed get unStrokd() { return this.selectedDoc?.color ? true : false; }
+    @computed get widthStk() { return this.getField("strokeWidth") || "1"; }
+    @computed get markHead() { return this.getField("strokeStartMarker") || ""; }
+    @computed get markTail() { return this.getField("strokeEndMarker") || ""; }
+    set solidStk(value) { this.dashdStk = ""; this.unStrokd = !value; }
+    set dashdStk(value) {
+        value && (this._lastDash = value) && (this.unStrokd = false);
+        this.selectedDoc && (this.selectedDoc.strokeDash = value ? this._lastDash : undefined);
+    }
+    set widthStk(value) { this.selectedDoc && (this.selectedDoc.strokeWidth = Number(value)); }
+    set unStrokd(value) { this.colorStk = value ? "" : this._lastLine; }
+    set markHead(value) { this.selectedDoc && (this.selectedDoc.strokeStartMarker = value); }
+    set markTail(value) { this.selectedDoc && (this.selectedDoc.strokeEndMarker = value); }
 
 
+    @computed get stkInput() { return this.regInput("stk", this.widthStk, (val: string) => this.widthStk = val); }
 
 
+    regInput = (key: string, value: any, setter: (val: string) => {}) => {
+        return <div className="inputBox">
+            <input className="inputBox-input"
+                type="text" value={value}
+                onChange={e => setter(e.target.value)} />
+            <div className="inputBox-button">
+                <div className="inputBox-button-up" key="up2"
+                    onPointerDown={undoBatch(action(() => this.upDownButtons("up", key)))} >
+                    <FontAwesomeIcon icon="caret-up" color="white" size="sm" />
+                </div>
+                <div className="inputbox-Button-down" key="down2"
+                    onPointerDown={undoBatch(action(() => this.upDownButtons("down", key)))} >
+                    <FontAwesomeIcon icon="caret-down" color="white" size="sm" />
+                </div>
+            </div>
+        </div>;
+    }
+
+    @computed get widthAndDash() {
+        return <div>{(this.solidStk || this.dashdStk) ? "Width" : ""}
+            {(this.solidStk || this.dashdStk) ? this.stkInput : ""}
+
+
+            {(this.solidStk || this.dashdStk) ? <input type="range"
+                defaultValue={Number(this.widthStk)} min={1} max={100}
+                onChange={undoBatch(action((e) => this.widthStk = e.target.value))} /> : (null)}
+            <br />
+            {(this.solidStk || this.dashdStk) ? <>
+                <p style={{ position: "absolute", fontSize: 12 }}>Arrow Head</p>
+                <input key="markHead" className="formatShapePane-inputBtn" type="checkbox"
+                    checked={this.markHead !== ""}
+                    onChange={undoBatch(action(() => this.markHead = this.markHead ? "" : "arrow"))}
+                    style={{ position: "absolute", right: 110, width: 20 }} />
+                <p style={{ position: "absolute", fontSize: 12, right: 30 }}>Arrow End</p>
+                <input key="markTail" className="formatShapePane-inputBtn" type="checkbox"
+                    checked={this.markTail !== ""}
+                    onChange={undoBatch(action(() => this.markTail = this.markTail ? "" : "arrow"))}
+                    style={{ position: "absolute", right: 0, width: 20 }} />
+                <br />
+            </> : ""}
+                Dash:
+            <input key="markHead" className="formatShapePane-inputBtn"
+                type="checkbox" checked={this.dashdStk === "2"}
+                onChange={undoBatch(action(() => this.dashdStk = this.dashdStk === "2" ? "0" : "2"))}
+                style={{ position: "absolute", right: 110, width: 20 }} />
+        </div>;
+    }
 
-    @computed get appearanceEditor() { return "appearance" };
+    @computed get appearanceEditor() {
+        return <div className="appearance-editor">
+            {this.widthAndDash}
+            {this.strokeAndFill}
+        </div>;
+    }
 
     @computed get transformEditor() {
         return <div className="transform-editor">
@@ -577,7 +713,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
             {this.XpsInput}
             {this.rotInput}
         </div>;
-    };
+    }
 
     render() {
 
-- 
cgit v1.2.3-70-g09d2


From 494129f2e5d673f11087ce0477feaa80e453dae4 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Fri, 31 Jul 2020 15:33:15 -0500
Subject: layout fix

---
 src/client/views/collections/collectionFreeForm/PropertiesView.tsx | 1 +
 1 file changed, 1 insertion(+)

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

diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 013b4be34..c187ad3b8 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -254,6 +254,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                     pinToPres={emptyFunction}
                     bringToFront={returnFalse}
                     ContentScaling={returnOne}
+                    dontRegisterView={true}
                 />
             </div>;
         } else {
-- 
cgit v1.2.3-70-g09d2


From 49ff32114387b5875e5cfb804a741caf24424612 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 31 Jul 2020 17:55:39 -0400
Subject: fixed dragging properties

---
 src/client/views/MainView.tsx                      | 204 ++++++++-------------
 .../collectionFreeForm/PropertiesView.tsx          |   2 +-
 2 files changed, 76 insertions(+), 130 deletions(-)

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

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 8e4851b6e..6009f7dab 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -300,7 +300,7 @@ export class MainView extends React.Component {
 
     @action
     onResize = (r: any) => {
-        this._panelWidth = r.offset.width - this.propertiesWidth();
+        this._panelWidth = r.offset.width;// - this.propertiesWidth();
         this._panelHeight = r.offset.height;
     }
 
@@ -368,102 +368,37 @@ export class MainView extends React.Component {
         TraceMobx();
         const mainContainer = this.mainContainer;
         const width = this.flyoutWidth;
-        return <Measure offset onResize={this.onResize}>
-            {({ measureRef }) =>
-                <div ref={measureRef} className="mainContent-div" onDrop={this.onDrop} style={{ width: `calc(100% - ${width}px)` }}>
-                    {!mainContainer ? (null) : this.mainDocView}
-                </div>
-            }
-        </Measure>;
+        return <div className="mainContent-div" onDrop={this.onDrop} style={{ width: `calc(100% - ${width}px)` }}>
+            {!mainContainer ? (null) : this.mainDocView}
+        </div>;
     }
 
     _canClick = false;
 
     @action
-    onPointerDown = (e: React.PointerEvent) => {
-        if (this._flyoutTranslate) {
-            this.panelContent = "none";
-            this._canClick = true;
-            this._flyoutSizeOnDown = e.clientX;
-            document.removeEventListener("pointermove", this.onPointerMove);
-            document.removeEventListener("pointerup", this.onPointerUp);
-            document.addEventListener("pointermove", this.onPointerMove);
-            document.addEventListener("pointerup", this.onPointerUp);
-            e.stopPropagation();
-            e.preventDefault();
-        }
-    }
-
-    @action
-    pointerLeaveDragger = () => {
-        if (!this._flyoutTranslate) {
-            this.flyoutWidth = 0;
-            this._flyoutTranslate = true;
-        }
-    }
-
-    @action
-    onDown = (e: React.PointerEvent) => {
-        this.propertiesDownX = e.screenX;
-        document.removeEventListener("pointermove", this.onPointerMove);
-        document.removeEventListener("pointerup", this.onPointerUp);
-        document.addEventListener("pointermove", this.onPointerMove);
-        document.addEventListener("pointerup", this.onPointerUp);
-        e.stopPropagation();
-        e.preventDefault();
-        // setupMoveUpEvents(this, e, action((e: PointerEvent, down: number[], delta: number[]) => {
-        //     this._propertiesWidth = this._panelWidth - Math.max(Transform.Identity().transformPoint(e.clientX, 0)[0], 0);
-        //     return false;
-        // }), returnFalse, action(() => this._propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this._panelWidth - 50, 200) : 0), false);
+    onPropertiesPointerDown = (e: React.PointerEvent) => {
+        setupMoveUpEvents(this, e, action((e: PointerEvent, down: number[], delta: number[]) => {
+            this._propertiesWidth = this._panelWidth - e.clientX;
+            return false;
+        }), returnFalse, action(() => this._propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this._panelWidth - 50, 200) : 0), false);
     }
 
     @action
-    onPointerMove = (e: PointerEvent) => {
-        if (this.propertiesDownX) {
-            this._propertiesWidth = this._propertiesWidth + (this.propertiesDownX - e.screenX);
-            if (this._propertiesWidth < 150) {
-                this._propertiesWidth = 0;
-                this.propertiesDownX = undefined;
-            } else if (this._propertiesWidth > 400) {
-                this._propertiesWidth = 400;
-                this.propertiesDownX = undefined;
-            }
-            document.removeEventListener("pointermove", this.onPointerMove);
-            document.removeEventListener("pointerup", this.onPointerUp);
-        } else {
-            this.flyoutWidth = Math.max(e.clientX, 0);
-            Math.abs(this.flyoutWidth - this._flyoutSizeOnDown) > 6 && (this._canClick = false);
-            this.sidebarButtonsDoc._columnWidth = this.flyoutWidth / 3 - 30;
-        }
-    }
-    @action
-    onPointerUp = (e: PointerEvent) => {
-        if (this.propertiesDownX) {
-            if (Math.abs(this.propertiesDownX - e.screenX) < 3) {
-                if (this._propertiesWidth < 10) {
-                    this._propertiesWidth = 200;
-                } else {
-                    this._propertiesWidth = 0;
-                }
-            } else {
-                this._propertiesWidth = this._propertiesWidth + (this.propertiesDownX - e.screenX);
-                if (this._propertiesWidth < 150) {
-                    this._propertiesWidth = 0;
-                } else if (this._propertiesWidth > 400) {
-                    this._propertiesWidth = 400;
-                }
-            }
-            this.propertiesDownX = undefined;
-        } else {
-            if (Math.abs(e.clientX - this._flyoutSizeOnDown) < 4 && this._canClick) {
+    onFlyoutPointerDown = (e: React.PointerEvent) => {
+        this.panelContent = "none";
+        if (this._flyoutTranslate) {
+            setupMoveUpEvents(this, e, action((e: PointerEvent) => {
+                this.flyoutWidth = Math.max(e.clientX, 0);
+                Math.abs(this.flyoutWidth - this._flyoutSizeOnDown) > 6 && (this._canClick = false);
+                this.sidebarButtonsDoc._columnWidth = this.flyoutWidth / 3 - 30;
+                return false;
+            }), emptyFunction, action(() => {
                 this.flyoutWidth = this.flyoutWidth < 15 ? 250 : 0;
                 this.flyoutWidth && (this.sidebarButtonsDoc._columnWidth = this.flyoutWidth / 3 - 30);
-            }
+            }));
         }
-        document.removeEventListener("pointermove", this.onPointerMove);
-        document.removeEventListener("pointerup", this.onPointerUp);
-
     }
+
     flyoutWidthFunc = () => this.flyoutWidth;
     addDocTabFunc = (doc: Doc, where: string, libraryPath?: Doc[]): boolean => {
         return where === "close" ? CollectionDockingView.CloseRightSplit(doc) :
@@ -603,56 +538,67 @@ export class MainView extends React.Component {
         </div>;
     }
 
+    @computed get mainInnerContent() {
+        const rightFlyout = this.propertiesWidth() - 1;
+        return <>
+            {this.menuPanel}
+            <div style={{ display: "contents", flexDirection: "row", position: "relative" }}>
+                <div className="mainView-flyoutContainer" style={{ width: this.flyoutWidth }}>
+                    {this.flyoutWidth !== 0 ? <div className="mainView-libraryHandle"
+                        onPointerDown={this.onFlyoutPointerDown}
+                        style={{ backgroundColor: this.defaultBackgroundColors(undefined) }}>
+                        <span title="library View Dragger" style={{
+                            width: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "100%" : "3vw",
+                            //height: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "100%" : "100vh",
+                            position: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "absolute" : "fixed",
+                            top: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "" : "0"
+                        }} />
+                        <div className="mainview-libraryHandle-icon">
+                            <FontAwesomeIcon icon="chevron-left" color="black" size="sm" /> </div>
+                    </div> : null}
+                    <div className="mainView-libraryFlyout" style={{
+                        //transformOrigin: this._flyoutTranslate ? "" : "left center",
+                        transition: this._flyoutTranslate ? "" : "width .5s",
+                        //transform: `scale(${this._flyoutTranslate ? 1 : 0.8})`,
+                        boxShadow: this._flyoutTranslate ? "" : "rgb(156, 147, 150) 0.2vw 0.2vw 0.2vw"
+                    }}>
+                        {this.flyout}
+                        {this.expandButton}
+                    </div>
+                </div>
+                {this.dockingContent}
+                {this.showProperties ? (null) :
+                    <div className="mainView-propertiesDragger" title="Properties View Dragger" onPointerDown={this.onPropertiesPointerDown}
+                        style={{ right: rightFlyout, top: "45%" }}>
+                        <div className="mainView-propertiesDragger-icon">
+                            <FontAwesomeIcon icon={this.propertiesIcon} color="white" size="sm" /> </div>
+                    </div>
+                }
+                {this.propertiesWidth() < 10 ? (null) :
+                    <div style={{ width: this.propertiesWidth() }}> {this.propertiesView} </div>}
+            </div>
+        </>;
+    }
+
     @computed get mainContent() {
         //const n = (RichTextMenu.Instance?.Pinned ? 1 : 0) + (CollectionMenu.Instance?.Pinned ? 1 : 0);
         const n = (CollectionMenu.Instance?.Pinned ? 1 : 0);
         const height = `calc(100% - ${n * Number(ANTIMODEMENU_HEIGHT.replace("px", ""))}px)`;
-
-        const rightFlyout = this.propertiesWidth() - 1;
+        const pinned = FormatShapePane.Instance?.Pinned;
+        const innerContent = this.mainInnerContent;
         return !this.userDoc ? (null) : (
-            <div className="mainView-mainContent" style={{
-                color: this.darkScheme ? "rgb(205,205,205)" : "black",
-                //change to times 2 for both pinned
-                height,
-                width: (FormatShapePane.Instance?.Pinned) ? `calc(100% - 200px)` : "100%"
-            }} >
-                {this.menuPanel}
-                <div style={{ display: "contents", flexDirection: "row", position: "relative" }}>
-                    <div className="mainView-flyoutContainer" onPointerLeave={this.pointerLeaveDragger} style={{ width: this.flyoutWidth }}>
-                        {this.flyoutWidth !== 0 ? <div className="mainView-libraryHandle"
-                            onPointerDown={this.onPointerDown}
-                            style={{ backgroundColor: this.defaultBackgroundColors(undefined) }}>
-                            <span title="library View Dragger" style={{
-                                width: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "100%" : "3vw",
-                                //height: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "100%" : "100vh",
-                                position: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "absolute" : "fixed",
-                                top: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "" : "0"
-                            }} />
-                            <div className="mainview-libraryHandle-icon">
-                                <FontAwesomeIcon icon="chevron-left" color="black" size="sm" /> </div>
-                        </div> : null}
-                        <div className="mainView-libraryFlyout" style={{
-                            //transformOrigin: this._flyoutTranslate ? "" : "left center",
-                            transition: this._flyoutTranslate ? "" : "width .5s",
-                            //transform: `scale(${this._flyoutTranslate ? 1 : 0.8})`,
-                            boxShadow: this._flyoutTranslate ? "" : "rgb(156, 147, 150) 0.2vw 0.2vw 0.2vw"
-                        }}>
-                            {this.flyout}
-                            {this.expandButton}
-                        </div>
+            <Measure offset onResize={this.onResize}>
+                {({ measureRef }) =>
+                    <div className="mainView-mainContent" ref={measureRef} style={{
+                        color: this.darkScheme ? "rgb(205,205,205)" : "black",
+                        //change to times 2 for both pinned
+                        height,
+                        width: pinned ? `calc(100% - 200px)` : "100%"
+                    }} >
+                        {innerContent}
                     </div>
-                    {this.dockingContent}
-                    {this.showProperties ? (null) :
-                        <div className="mainView-propertiesDragger" title="Properties View Dragger" onPointerDown={this.onDown}
-                            style={{ right: rightFlyout, top: "45%" }}>
-                            <div className="mainView-propertiesDragger-icon">
-                                <FontAwesomeIcon icon={this.propertiesIcon} color="white" size="sm" /> </div>
-                        </div>
-                    }
-                    {this.propertiesWidth() < 10 ? (null) :
-                        <div style={{ width: this.propertiesWidth() }}> {this.propertiesView} </div>}
-                </div>
-            </div>);
+                }
+            </Measure>);
     }
 
     public static expandFlyout = action(() => {
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index c187ad3b8..a3c9516e1 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -295,7 +295,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
     sharingItem(name: string, effectiveAcl: symbol, permission?: string) {
-        return <div className="propertiesView-sharingTable-item">
+        return <div className="propertiesView-sharingTable-item" key="name">
             <div className="propertiesView-sharingTable-item-name" style={{ width: name !== "Me" ? "70px" : "80px" }}> {name} </div>
             {name !== "Me" ? this.notifyIcon : null}
             <div className="propertiesView-sharingTable-item-permission">
-- 
cgit v1.2.3-70-g09d2


From b33e31e369aef6e0675219c96ba4b8a058a69b0c Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sat, 1 Aug 2020 09:39:38 -0400
Subject: fixed warnings

---
 src/client/views/DocumentDecorations.tsx           |  8 +++----
 src/client/views/MainView.tsx                      |  4 ++--
 src/client/views/PreviewCursor.tsx                 |  6 +++---
 src/client/views/PropertiesButtons.tsx             |  2 +-
 .../views/collections/CollectionDockingView.tsx    |  6 +++---
 src/client/views/collections/CollectionMenu.tsx    |  4 ++--
 src/client/views/collections/CollectionSubView.tsx |  2 +-
 .../views/collections/CollectionTreeView.tsx       |  2 +-
 .../views/collections/ParentDocumentSelector.tsx   |  6 +++---
 src/client/views/collections/SchemaTable.tsx       |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  4 ++--
 .../collectionFreeForm/FormatShapePane.tsx         | 25 +++++++++++-----------
 .../collectionFreeForm/PropertiesView.tsx          | 14 +++++-------
 src/client/views/nodes/DocumentView.tsx            |  2 +-
 .../views/nodes/formattedText/RichTextMenu.tsx     |  4 ++--
 src/client/views/nodes/formattedText/nodes_rts.ts  |  8 +++----
 src/fields/Doc.ts                                  |  6 +++---
 src/server/ApiManagers/UtilManager.ts              |  1 -
 18 files changed, 50 insertions(+), 56 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index bdb25d460..ec6e2be7c 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -528,12 +528,12 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 const ink = Cast(doc.data, InkField)?.inkData;
                 if (ink) {
                     const newPoints: { X: number, Y: number }[] = [];
-                    for (var i = 0; i < ink.length; i++) {
+                    ink.forEach(i => {
                         // (new x — oldx) + (oldxpoint * newWidt)/oldWidth 
-                        const newX = (doc.x - this._inkDocs[index].x) + (ink[i].X * doc._width) / this._inkDocs[index].width;
-                        const newY = (doc.y - this._inkDocs[index].y) + (ink[i].Y * doc._height) / this._inkDocs[index].height;
+                        const newX = ((doc.x || 0) - this._inkDocs[index].x) + (i.X * (doc._width || 0)) / this._inkDocs[index].width;
+                        const newY = ((doc.y || 0) - this._inkDocs[index].y) + (i.Y * (doc._height || 0)) / this._inkDocs[index].height;
                         newPoints.push({ X: newX, Y: newY });
-                    }
+                    });
                     doc.data = new InkField(newPoints);
 
                 }
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 85f695b85..67f1f5592 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -305,7 +305,7 @@ export class MainView extends React.Component {
     }
 
     @action
-    getPWidth = () => this._panelWidth - this.propertiesWidth();
+    getPWidth = () => this._panelWidth - this.propertiesWidth()
 
     getPHeight = () => this._panelHeight;
     getContentsHeight = () => this._panelHeight - this._buttonBarHeight;
@@ -406,7 +406,7 @@ export class MainView extends React.Component {
     //sidebarScreenToLocal = () => new Transform(0, (RichTextMenu.Instance.Pinned ? -35 : 0) + (CollectionMenu.Instance.Pinned ? -35 : 0), 1);
     mainContainerXf = () => this.sidebarScreenToLocal().translate(0, -this._buttonBarHeight);
 
-    @computed get closePosition() { return 55 + this.flyoutWidth }
+    @computed get closePosition() { return 55 + this.flyoutWidth; }
     @computed get flyout() {
         if (!this.sidebarContent) return null;
         return <div className="mainView-libraryFlyout">
diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx
index b4116e980..d7034fcfb 100644
--- a/src/client/views/PreviewCursor.tsx
+++ b/src/client/views/PreviewCursor.tsx
@@ -112,10 +112,10 @@ export class PreviewCursor extends React.Component<{}> {
                 } else if (e.clipboardData.items.length) {
                     const batch = UndoManager.StartBatch("collection view drop");
                     const files: File[] = [];
-                    for (let i = 0; i < e.clipboardData.items.length; i++) {
-                        const file = e.clipboardData.items[i].getAsFile();
+                    Array.from(e.clipboardData.items).forEach(item => {
+                        const file = item.getAsFile();
                         file && files.push(file);
-                    }
+                    });
                     const generatedDocuments = await DocUtils.uploadFilesToDocs(files, { x: newPoint[0], y: newPoint[1] });
                     generatedDocuments.forEach(PreviewCursor._addDocument);
                     batch.end();
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index bd5301629..59e7cc7c8 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -464,7 +464,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
             <div className={"propertiesButtons-linkButton-empty"}
                 onPointerDown={() => {
                     if (this.selectedDocumentView) {
-                        GooglePhotos.Export.CollectionToAlbum({ collection: this.selectedDocumentView.Document }).then(console.log)
+                        GooglePhotos.Export.CollectionToAlbum({ collection: this.selectedDocumentView.Document }).then(console.log);
                     }
                 }}>
                 {<FontAwesomeIcon className="documentdecorations-icon"
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 9ce5cb03b..7a0a06069 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -521,7 +521,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                 tab.element[0].onpointerdown = (e: any) => {
                     const view = DocumentManager.Instance.getDocumentView(doc);
                     view && SelectionManager.SelectDoc(view, false);
-                }
+                };
                 // shifts the focus to this tab when another tab is dragged over it
                 tab.element[0].onmouseenter = (e: any) => {
                     if (!this._isPointerDown || !SnappingManager.GetIsDragging()) return;
@@ -747,10 +747,10 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
         this.onActiveContentItemChanged();
         this._tabReaction = reaction(() => ({ views: SelectionManager.SelectedDocuments(), color: StrCast(this._document?._backgroundColor, "white") }),
             (data) => {
-                const selected = data.views.some(v => Doc.AreProtosEqual(v.props.Document, this._document))
+                const selected = data.views.some(v => Doc.AreProtosEqual(v.props.Document, this._document));
                 this._tab.style.backgroundColor = selected ? data.color : "";
             }
-        )
+        );
     }
 
     componentWillUnmount() {
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index e70a16da9..01374cfbb 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -49,7 +49,7 @@ export default class CollectionMenu extends AntimodeMenu {
 
     componentDidMount() {
         reaction(() => SelectionManager.SelectedDocuments().length && SelectionManager.SelectedDocuments()[0],
-            (doc) => doc && this.SetSelection(doc))
+            (doc) => doc && this.SetSelection(doc));
     }
 
     @action
@@ -162,7 +162,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
         initialize: (button: Doc) => { button['target-docFilters'] = this.target._docFilters instanceof ObjectField ? ObjectField.MakeCopy(this.target._docFilters as any as ObjectField) : ""; },
     };
 
-    @computed get _freeform_commands() { return Doc.UserDoc().noviceMode ? [this._viewCommand, this._saveFilterCommand] : [this._viewCommand, this._saveFilterCommand, this._contentCommand, this._templateCommand, this._narrativeCommand] };
+    @computed get _freeform_commands() { return Doc.UserDoc().noviceMode ? [this._viewCommand, this._saveFilterCommand] : [this._viewCommand, this._saveFilterCommand, this._contentCommand, this._templateCommand, this._narrativeCommand]; }
 
     _stacking_commands = [this._contentCommand, this._templateCommand];
     _masonry_commands = [this._contentCommand, this._templateCommand];
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 9f78c15eb..c90e85271 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -296,7 +296,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
                             const reg = new RegExp(Utils.prepend(""), "g");
                             const modHtml = srcUrl ? html.replace(reg, srcUrl) : html;
                             const htmlDoc = Docs.Create.HtmlDocument(modHtml, { ...options, title: "-web page-", _width: 300, _height: 300 });
-                            Doc.GetProto(htmlDoc)["data-text"] = Doc.GetProto(htmlDoc)["text"] = text;
+                            Doc.GetProto(htmlDoc)["data-text"] = Doc.GetProto(htmlDoc).text = text;
                             this.props.addDocument(htmlDoc);
                             if (srcWeb) {
                                 const focusNode = (SelectionManager.SelectedDocuments()[0].ContentDiv?.getElementsByTagName("iframe")[0].contentDocument?.getSelection()?.focusNode as any);
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index d6203e7da..ca3ab8866 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -104,7 +104,7 @@ class TreeView extends React.Component<TreeViewProps> {
         const layout = Doc.LayoutField(this.doc) instanceof Doc ? Doc.LayoutField(this.doc) as Doc : undefined;
         return ((this.props.dataDoc ? DocListCast(this.props.dataDoc[field]) : undefined) || // if there's a data doc for an expanded template, use it's data field
             (layout ? DocListCast(layout[field]) : undefined) || // else if there's a layout doc, display it's fields
-            DocListCast(this.doc[field])) as Doc[]; // otherwise use the document's data field
+            DocListCast(this.doc[field])); // otherwise use the document's data field
     }
     @computed get childDocs() { return this.childDocList(this.fieldKey); }
     @computed get childLinks() { return this.childDocList("links"); }
diff --git a/src/client/views/collections/ParentDocumentSelector.tsx b/src/client/views/collections/ParentDocumentSelector.tsx
index 8c0b8de9d..532dd6abc 100644
--- a/src/client/views/collections/ParentDocumentSelector.tsx
+++ b/src/client/views/collections/ParentDocumentSelector.tsx
@@ -42,14 +42,14 @@ export class SelectorContextMenu extends React.Component<SelectorProps> {
     async fetchDocuments() {
         const aliases = (await SearchUtil.GetAliasesOfDocument(this.props.Document));
         const containerProtoSets = await Promise.all(aliases.map(async alias =>
-            await Promise.all((await SearchUtil.Search("", true, { fq: `data_l:"${alias[Id]}"` })).docs)));
+            ((await SearchUtil.Search("", true, { fq: `data_l:"${alias[Id]}"` })).docs)));
         const containerProtos = containerProtoSets.reduce((p, set) => { set.map(s => p.add(s)); return p; }, new Set<Doc>());
         const containerSets = await Promise.all(Array.from(containerProtos.keys()).map(async container => {
-            return (await SearchUtil.GetAliasesOfDocument(container));
+            return (SearchUtil.GetAliasesOfDocument(container));
         }));
         const containers = containerSets.reduce((p, set) => { set.map(s => p.add(s)); return p; }, new Set<Doc>());
         const doclayoutSets = await Promise.all(Array.from(containers.keys()).map(async (dp) => {
-            return (await SearchUtil.GetAliasesOfDocument(dp));
+            return (SearchUtil.GetAliasesOfDocument(dp));
         }));
         const doclayouts = Array.from(doclayoutSets.reduce((p, set) => { set.map(s => p.add(s)); return p; }, new Set<Doc>()).keys());
         runInAction(() => {
diff --git a/src/client/views/collections/SchemaTable.tsx b/src/client/views/collections/SchemaTable.tsx
index 75e693f96..7e2840c2c 100644
--- a/src/client/views/collections/SchemaTable.tsx
+++ b/src/client/views/collections/SchemaTable.tsx
@@ -148,7 +148,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     @action
-    changeTitleMode = () => this._showTitleDropdown = !this._showTitleDropdown;
+    changeTitleMode = () => this._showTitleDropdown = !this._showTitleDropdown
 
     @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
     @computed get tableColumns(): Column<Doc>[] {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index e0981d797..badbc48a1 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1144,7 +1144,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
     @action
     componentDidMount() {
         super.componentDidMount?.();
-        this._layoutComputeReaction = reaction(() => { TraceMobx(); return this.doLayoutComputation },
+        this._layoutComputeReaction = reaction(() => this.doLayoutComputation,
             (elements) => this._layoutElements = elements || [],
             { fireImmediately: true, name: "doLayout" });
 
@@ -1292,7 +1292,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
                         setTimeout(() => {
                             SearchUtil.Search(`{!join from=id to=proto_i}id:link*`, true, {}).then(docs => {
                                 docs.docs.forEach(d => LinkManager.Instance.addLink(d));
-                            })
+                            });
                         }, 2000); // need to give solr some time to update so that this query will find any link docs we've added.
                     }
                 }
diff --git a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
index eb6097acf..6263be261 100644
--- a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
+++ b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
@@ -13,7 +13,6 @@ import AntimodeMenu from "../../AntimodeMenu";
 import "./FormatShapePane.scss";
 import { undoBatch } from "../../../util/UndoManager";
 import { ColorState, SketchPicker } from 'react-color';
-import { DocumentView } from "../../../views/nodes/DocumentView"
 
 @observer
 export default class FormatShapePane extends AntimodeMenu {
@@ -124,12 +123,12 @@ export default class FormatShapePane extends AntimodeMenu {
                     console.log(ink);
                     if (ink) {
                         const newPoints: { X: number, Y: number }[] = [];
-                        for (var j = 0; j < ink.length; j++) {
+                        ink.forEach(i => {
                             // (new x — oldx) + (oldxpoint * newWidt)/oldWidth 
-                            const newX = (doc.x - oldX) + (ink[j].X * doc._width) / oldWidth;
-                            const newY = (doc.y - oldY) + (ink[j].Y * doc._height) / oldHeight;
+                            const newX = ((doc.x || 0) - oldX) + (i.X * (doc._width || 0)) / oldWidth;
+                            const newY = ((doc.y || 0) - oldY) + (i.Y * (doc._height || 0)) / oldHeight;
                             newPoints.push({ X: newX, Y: newY });
-                        }
+                        });
                         doc.data = new InkField(newPoints);
                     }
                 }
@@ -148,12 +147,12 @@ export default class FormatShapePane extends AntimodeMenu {
                     console.log(ink);
                     if (ink) {
                         const newPoints: { X: number, Y: number }[] = [];
-                        for (var j = 0; j < ink.length; j++) {
+                        ink.forEach(i => {
                             // (new x — oldx) + (oldxpoint * newWidt)/oldWidth 
-                            const newX = (doc.x - oldX) + (ink[j].X * doc._width) / oldWidth;
-                            const newY = (doc.y - oldY) + (ink[j].Y * doc._height) / oldHeight;
+                            const newX = ((doc.x || 0) - oldX) + (i.X * (doc._width || 0)) / oldWidth;
+                            const newY = ((doc.y || 0) - oldY) + (i.Y * (doc._height || 0)) / oldHeight;
                             newPoints.push({ X: newX, Y: newY });
-                        }
+                        });
                         doc.data = new InkField(newPoints);
                     }
                 }
@@ -191,11 +190,11 @@ export default class FormatShapePane extends AntimodeMenu {
                 if (ink) {
 
                     const newPoints: { X: number, Y: number }[] = [];
-                    for (var i = 0; i < ink.length; i++) {
-                        const newX = Math.cos(angle) * (ink[i].X - _centerPoints[index].X) - Math.sin(angle) * (ink[i].Y - _centerPoints[index].Y) + _centerPoints[index].X;
-                        const newY = Math.sin(angle) * (ink[i].X - _centerPoints[index].X) + Math.cos(angle) * (ink[i].Y - _centerPoints[index].Y) + _centerPoints[index].Y;
+                    ink.forEach(i => {
+                        const newX = Math.cos(angle) * (i.X - _centerPoints[index].X) - Math.sin(angle) * (i.Y - _centerPoints[index].Y) + _centerPoints[index].X;
+                        const newY = Math.sin(angle) * (i.X - _centerPoints[index].X) + Math.cos(angle) * (i.Y - _centerPoints[index].Y) + _centerPoints[index].Y;
                         newPoints.push({ X: newX, Y: newY });
-                    }
+                    });
                     doc.data = new InkField(newPoints);
                     const xs = newPoints.map(p => p.X);
                     const ys = newPoints.map(p => p.Y);
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index a3c9516e1..ca81bf131 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -399,11 +399,11 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 if (ink) {
 
                     const newPoints: { X: number, Y: number }[] = [];
-                    for (var i = 0; i < ink.length; i++) {
-                        const newX = Math.cos(angle) * (ink[i].X - _centerPoints[index].X) - Math.sin(angle) * (ink[i].Y - _centerPoints[index].Y) + _centerPoints[index].X;
-                        const newY = Math.sin(angle) * (ink[i].X - _centerPoints[index].X) + Math.cos(angle) * (ink[i].Y - _centerPoints[index].Y) + _centerPoints[index].Y;
+                    ink.forEach(i => {
+                        const newX = Math.cos(angle) * (i.X - _centerPoints[index].X) - Math.sin(angle) * (i.Y - _centerPoints[index].Y) + _centerPoints[index].X;
+                        const newY = Math.sin(angle) * (i.X - _centerPoints[index].X) + Math.cos(angle) * (i.Y - _centerPoints[index].Y) + _centerPoints[index].Y;
                         newPoints.push({ X: newX, Y: newY });
-                    }
+                    });
                     doc.data = new InkField(newPoints);
                     const xs = newPoints.map(p => p.X);
                     const ys = newPoints.map(p => p.Y);
@@ -534,11 +534,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
     getField(key: string) {
-        //if (this.selectedDoc) {
-        return Field.toString(this.selectedDoc[key] as Field);
-        // } else {
-        //     return undefined as Opt<string>;
-        // }
+        return Field.toString(this.selectedDoc?.[key] as Field);
     }
 
     @computed get shapeXps() { return this.getField("x"); }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 62a786a03..80db0e6db 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -325,7 +325,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                     thisContainer: this.props.ContainingCollectionDoc,
                     shiftKey: e.shiftKey
                 }, console.log);
-                if (this.props.Document !== Doc.UserDoc()["dockedBtn-undo"] && this.props.Document !== Doc.UserDoc()["dockedBtn-redo"]) {
+                if (!Doc.AreProtosEqual(this.props.Document, Doc.UserDoc()["dockedBtn-undo"] as Doc) && !Doc.AreProtosEqual(this.props.Document, Doc.UserDoc()["dockedBtn-redo"] as Doc)) {
                     UndoManager.RunInBatch(func, "on click");
                 } else func();
             } else if (this.Document["onClick-rawScript"] && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes("ScriptingBox")) {// bcz: hack? don't edit a script if you're clicking on a scripting box itself
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index be8d3faeb..f76707a79 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -530,7 +530,7 @@ export default class RichTextMenu extends AntimodeMenu {
 
     indentParagraph(state: EditorState<any>, dispatch: any) {
         var tr = state.tr;
-        let headin = false;
+        const heading = false;
         state.doc.nodesBetween(state.selection.from, state.selection.to, (node, pos, parent, index) => {
             if (node.type === schema.nodes.paragraph || node.type === schema.nodes.heading) {
                 const nodeval = node.attrs.indent ? Number(node.attrs.indent) : undefined;
@@ -540,7 +540,7 @@ export default class RichTextMenu extends AntimodeMenu {
             }
             return true;
         });
-        !headin && dispatch?.(tr);
+        !heading && dispatch?.(tr);
         return true;
     }
 
diff --git a/src/client/views/nodes/formattedText/nodes_rts.ts b/src/client/views/nodes/formattedText/nodes_rts.ts
index 0eca6d753..1616500f6 100644
--- a/src/client/views/nodes/formattedText/nodes_rts.ts
+++ b/src/client/views/nodes/formattedText/nodes_rts.ts
@@ -79,14 +79,14 @@ export const nodes: { [index: string]: NodeSpec } = {
         { tag: "h5", attrs: { level: 5 } },
         { tag: "h6", attrs: { level: 6 } }],
         toDOM(node) {
-            var dom = toParagraphDOM(node) as any;
-            var level = node.attrs.level || 1;
+            const dom = toParagraphDOM(node) as any;
+            const level = node.attrs.level || 1;
             dom[0] = 'h' + level;
             return dom;
         },
         getAttrs(dom: any) {
-            var attrs = getParagraphNodeAttrs(dom) as any;
-            var level = Number(dom.nodeName.substring(1)) || 1;
+            const attrs = getParagraphNodeAttrs(dom) as any;
+            const level = Number(dom.nodeName.substring(1)) || 1;
             attrs.level = level;
             return attrs;
         }
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 267defa4b..383adccdc 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -524,10 +524,10 @@ export namespace Doc {
             const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key]));
             const field = ProxyField.WithoutProxy(() => doc[key]);
             const copyObjectField = async (field: ObjectField) => {
-                const list = await Cast(doc[key], listSpec(Doc));
+                const list = Cast(doc[key], listSpec(Doc));
                 const docs = list && (await DocListCastAsync(list))?.filter(d => d instanceof Doc);
                 if (docs !== undefined && docs.length) {
-                    const clones = await Promise.all(docs.map(async d => await Doc.makeClone(d as Doc, cloneMap, rtfs, exclusions, dontCreate)));
+                    const clones = await Promise.all(docs.map(async d => Doc.makeClone(d, cloneMap, rtfs, exclusions, dontCreate)));
                     !dontCreate && assignKey(new List<Doc>(clones));
                 } else if (doc[key] instanceof Doc) {
                     assignKey(key.includes("layout[") ? undefined : key.startsWith("layout") ? doc[key] as Doc : await Doc.makeClone(doc[key] as Doc, cloneMap, rtfs, exclusions, dontCreate)); // reference documents except copy documents that are expanded teplate fields 
@@ -621,7 +621,7 @@ export namespace Doc {
         Array.from(map.entries()).forEach(f => docs[f[0]] = f[1]);
         const docString = JSON.stringify({ id: doc[Id], docs }, replacer);
 
-        var zip = new JSZip();
+        const zip = new JSZip();
 
         zip.file("doc.json", docString);
 
diff --git a/src/server/ApiManagers/UtilManager.ts b/src/server/ApiManagers/UtilManager.ts
index e2cd88726..e657866ce 100644
--- a/src/server/ApiManagers/UtilManager.ts
+++ b/src/server/ApiManagers/UtilManager.ts
@@ -6,7 +6,6 @@ import { exec } from 'child_process';
 
 // const recommender = new Recommender();
 // recommender.testModel();
-import executeImport from "../../scraping/buxton/final/BuxtonImporter";
 
 export default class UtilManager extends ApiManager {
 
-- 
cgit v1.2.3-70-g09d2


From 034e05b5bb587e361e9ab87160c9f3abddc9845b Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Sat, 1 Aug 2020 13:34:36 -0500
Subject: finished ink menu merge

---
 src/client/views/MainView.tsx                      |  4 +-
 src/client/views/PropertiesButtons.scss            | 12 +--
 src/client/views/collections/CollectionMenu.tsx    | 11 +--
 .../collectionFreeForm/PropertiesView.scss         | 90 ++++++++++++++++++++--
 .../collectionFreeForm/PropertiesView.tsx          | 88 +++++++++++++--------
 5 files changed, 153 insertions(+), 52 deletions(-)

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

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 74be36bda..993c6f4b6 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -378,7 +378,7 @@ export class MainView extends React.Component {
         setupMoveUpEvents(this, e, action((e: PointerEvent, down: number[], delta: number[]) => {
             this._propertiesWidth = this._panelWidth - e.clientX;
             return false;
-        }), returnFalse, action(() => this._propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this._panelWidth - 50, 200) : 0), false);
+        }), returnFalse, action(() => this._propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this._panelWidth - 50, 250) : 0), false);
     }
 
     @action
@@ -464,7 +464,7 @@ export class MainView extends React.Component {
                 onClick={undefined}
                 ScreenToLocalTransform={this.mainContainerXf}
                 ContentScaling={returnOne}
-                PanelWidth={() => 60}
+                PanelWidth={() => 70}
                 PanelHeight={this.getContentsHeight}
                 renderDepth={0}
                 focus={emptyFunction}
diff --git a/src/client/views/PropertiesButtons.scss b/src/client/views/PropertiesButtons.scss
index 11265b413..e099122c4 100644
--- a/src/client/views/PropertiesButtons.scss
+++ b/src/client/views/PropertiesButtons.scss
@@ -20,8 +20,8 @@ $linkGap : 3px;
 
 .propertiesButtons-linkButton-empty,
 .propertiesButtons-linkButton-nonempty {
-    height: 25px;
-    width: 25px;
+    height: 30px;
+    width: 30px;
     border-radius: 5px;
     opacity: 0.9;
     pointer-events: auto;
@@ -35,7 +35,7 @@ $linkGap : 3px;
     display: flex;
     justify-content: center;
     align-items: center;
-    margin-right: 5px;
+    margin-right: 10px;
 
     &:hover {
         background: $main-accent;
@@ -68,12 +68,12 @@ $linkGap : 3px;
     padding-right: 5px;
     width: 25px;
     border-radius: 5px;
-    margin-right: 8px;
+    margin-right: 18px;
 }
 
 .propertiesButtons-linker {
-    height: 25px;
-    width: 25px;
+    height: 30px;
+    width: 30px;
     text-align: center;
     border-radius: 5px;
     pointer-events: auto;
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 01374cfbb..498030b71 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -554,11 +554,12 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
     }
 
     @computed get formatPane() {
-        return <button className="antimodeMenu-button" key="format" title="toggle foramatting pane"
-            onPointerDown={action(e => FormatShapePane.Instance.Pinned = !FormatShapePane.Instance.Pinned)}
-            style={{ backgroundColor: this._fillBtn ? "121212" : "" }}>
-            <FontAwesomeIcon icon="angle-double-right" size="lg" />
-        </button>;
+        // return <button className="antimodeMenu-button" key="format" title="toggle foramatting pane"
+        //     onPointerDown={action(e => FormatShapePane.Instance.Pinned = !FormatShapePane.Instance.Pinned)}
+        //     style={{ backgroundColor: this._fillBtn ? "121212" : "" }}>
+        //     <FontAwesomeIcon icon="angle-double-right" size="lg" />
+        // </button>;
+        return null;
     }
 
     render() {
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index 0b23d2325..8847fe89d 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -221,7 +221,8 @@
         border: 1px solid black;
         padding: 5px;
         border-radius: 6px;
-        width: 170px;
+        /* width: 170px; */
+        margin-right: 10px;
         background-color: #ececec;
         max-height: 130px;
         overflow-y: scroll;
@@ -250,6 +251,9 @@
 
             .propertiesView-sharingTable-item-permission {
                 display: flex;
+                right: 34;
+                float: right;
+                position: absolute;
 
                 .permissions-select {
                     z-index: 1;
@@ -392,7 +396,7 @@
         width: 32;
         height: 32;
         padding-top: 9px;
-        margin-left: 5px;
+        margin-left: 18px;
 
         &:hover {
             background: rgb(131, 131, 131);
@@ -505,14 +509,14 @@
 }
 
 .strokeAndFill {
-
     display: flex;
+    margin-top: 10px;
 
     .fill {
-        margin-right: 30px;
+        margin-right: 40px;
         display: flex;
         padding-bottom: 7px;
-        margin-left: 20px;
+        margin-left: 35px;
 
         .fill-title {
             font-size: 12px;
@@ -538,4 +542,80 @@
             margin-top: -1px;
         }
     }
+}
+
+.widthAndDash {
+
+    .width {
+        .width-top {
+            display: flex;
+
+            .width-title {
+                font-size: 12;
+                margin-right: 20px;
+                margin-left: 35px;
+                text-align: center;
+            }
+
+            .width-input {
+                margin-right: 30px;
+                margin-top: -10px;
+            }
+        }
+
+        .width-range {
+            margin-right: 1px;
+            margin-bottom: 6;
+        }
+    }
+
+    .arrows {
+
+        display: flex;
+        margin-bottom: 3px;
+
+        .arrows-head {
+
+            display: flex;
+            margin-right: 35px;
+
+            .arrows-head-title {
+                font-size: 12;
+            }
+
+            .arrows-head-input {
+                margin-left: 6px;
+                margin-top: 2px;
+            }
+        }
+
+        .arrows-tail {
+            display: flex;
+
+            .arrows-tail-title {
+                font-size: 12;
+            }
+
+            .arrows-tail-input {
+                margin-left: 6px;
+                margin-top: 2px;
+            }
+        }
+    }
+
+    .dashed {
+
+        display: flex;
+        margin-left: 74px;
+        margin-bottom: 6px;
+
+        .dashed-title {
+            font-size: 12;
+        }
+
+        .dashed-input {
+            margin-left: 6px;
+            margin-top: 2px;
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index ca81bf131..f39a75b81 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -26,6 +26,7 @@ import { undoBatch } from "../../../util/UndoManager";
 import { ColorState, SketchPicker } from "react-color";
 import AntimodeMenu from "../../AntimodeMenu";
 import "./FormatShapePane.scss";
+import { discovery_v1 } from "googleapis";
 
 
 interface PropertiesViewProps {
@@ -295,7 +296,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
     sharingItem(name: string, effectiveAcl: symbol, permission?: string) {
-        return <div className="propertiesView-sharingTable-item" key="name">
+        return <div className="propertiesView-sharingTable-item">
             <div className="propertiesView-sharingTable-item-name" style={{ width: name !== "Me" ? "70px" : "80px" }}> {name} </div>
             {name !== "Me" ? this.notifyIcon : null}
             <div className="propertiesView-sharingTable-item-permission">
@@ -399,11 +400,11 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 if (ink) {
 
                     const newPoints: { X: number, Y: number }[] = [];
-                    ink.forEach(i => {
-                        const newX = Math.cos(angle) * (i.X - _centerPoints[index].X) - Math.sin(angle) * (i.Y - _centerPoints[index].Y) + _centerPoints[index].X;
-                        const newY = Math.sin(angle) * (i.X - _centerPoints[index].X) + Math.cos(angle) * (i.Y - _centerPoints[index].Y) + _centerPoints[index].Y;
+                    for (var i = 0; i < ink.length; i++) {
+                        const newX = Math.cos(angle) * (ink[i].X - _centerPoints[index].X) - Math.sin(angle) * (ink[i].Y - _centerPoints[index].Y) + _centerPoints[index].X;
+                        const newY = Math.sin(angle) * (ink[i].X - _centerPoints[index].X) + Math.cos(angle) * (ink[i].Y - _centerPoints[index].Y) + _centerPoints[index].Y;
                         newPoints.push({ X: newX, Y: newY });
-                    });
+                    }
                     doc.data = new InkField(newPoints);
                     const xs = newPoints.map(p => p.X);
                     const ys = newPoints.map(p => p.Y);
@@ -534,7 +535,11 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
     getField(key: string) {
-        return Field.toString(this.selectedDoc?.[key] as Field);
+        //if (this.selectedDoc) {
+        return Field.toString(this.selectedDoc[key] as Field);
+        // } else {
+        //     return undefined as Opt<string>;
+        // }
     }
 
     @computed get shapeXps() { return this.getField("x"); }
@@ -565,7 +570,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     private _lastFill = "#D0021B";
     private _lastLine = "#D0021B";
-    private _lastDash = "2";
+    private _lastDash: any = "2";
 
     @computed get colorFil() { const ccol = this.getField("fillColor") || ""; ccol && (this._lastFill = ccol); return ccol; }
     @computed get colorStk() { const ccol = this.getField("color") || ""; ccol && (this._lastLine = ccol); return ccol; }
@@ -629,7 +634,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
     @computed get solidStk() { return this.selectedDoc?.color && (!this.selectedDoc?.strokeDash || this.selectedDoc?.strokeDash === "0") ? true : false; }
-    @computed get dashdStk() { return !this.unStrokd && this.getField("strokeDash") || ""; }
+    @computed get dashdStk() { return this.selectedDoc?.strokeDash || ""; }
     @computed get unStrokd() { return this.selectedDoc?.color ? true : false; }
     @computed get widthStk() { return this.getField("strokeWidth") || "1"; }
     @computed get markHead() { return this.getField("strokeStartMarker") || ""; }
@@ -667,35 +672,50 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
     @computed get widthAndDash() {
-        return <div>{(this.solidStk || this.dashdStk) ? "Width" : ""}
-            {(this.solidStk || this.dashdStk) ? this.stkInput : ""}
-
-
-            {(this.solidStk || this.dashdStk) ? <input type="range"
-                defaultValue={Number(this.widthStk)} min={1} max={100}
-                onChange={undoBatch(action((e) => this.widthStk = e.target.value))} /> : (null)}
-            <br />
-            {(this.solidStk || this.dashdStk) ? <>
-                <p style={{ position: "absolute", fontSize: 12 }}>Arrow Head</p>
-                <input key="markHead" className="formatShapePane-inputBtn" type="checkbox"
-                    checked={this.markHead !== ""}
-                    onChange={undoBatch(action(() => this.markHead = this.markHead ? "" : "arrow"))}
-                    style={{ position: "absolute", right: 110, width: 20 }} />
-                <p style={{ position: "absolute", fontSize: 12, right: 30 }}>Arrow End</p>
-                <input key="markTail" className="formatShapePane-inputBtn" type="checkbox"
-                    checked={this.markTail !== ""}
-                    onChange={undoBatch(action(() => this.markTail = this.markTail ? "" : "arrow"))}
-                    style={{ position: "absolute", right: 0, width: 20 }} />
-                <br />
-            </> : ""}
-                Dash:
-            <input key="markHead" className="formatShapePane-inputBtn"
-                type="checkbox" checked={this.dashdStk === "2"}
-                onChange={undoBatch(action(() => this.dashdStk = this.dashdStk === "2" ? "0" : "2"))}
-                style={{ position: "absolute", right: 110, width: 20 }} />
+        return <div className="widthAndDash">
+            <div className="width">
+                <div className="width-top">
+                    <div className="width-title">Width:</div>
+                    <div className="width-input">{this.stkInput}</div>
+                </div>
+                <input className="width-range" type="range"
+                    defaultValue={Number(this.widthStk)} min={1} max={100}
+                    onChange={undoBatch(action((e) => this.widthStk = e.target.value))} />
+            </div>
+
+            <div className="arrows">
+                <div className="arrows-head">
+                    <div className="arrows-head-title" >Arrow Head: </div>
+                    <input key="markHead" className="arrows-head-input" type="checkbox"
+                        checked={this.markHead !== ""}
+                        onChange={undoBatch(action(() => this.markHead = this.markHead ? "" : "arrow"))} />
+                </div>
+                <div className="arrows-tail">
+                    <div className="arrows-tail-title" >Arrow End: </div>
+                    <input key="markTail" className="arrows-tail-input" type="checkbox"
+                        checked={this.markTail !== ""}
+                        onChange={undoBatch(action(() => this.markTail = this.markTail ? "" : "arrow"))} />
+                </div>
+            </div>
+            <div className="dashed">
+                <div className="dashed-title">Dash:</div>
+                <input key="markHead" className="dashed-input"
+                    type="checkbox" checked={this.dashdStk === "2"}
+                    onChange={this.changeDash} />
+            </div>
         </div>;
     }
 
+    @undoBatch @action
+    changeDash = () => {
+        const dash = this.dashdStk;
+        if (dash === "2") {
+            this.dashdStk = "0";
+        } else {
+            this.dashdStk = "2";
+        }
+    }
+
     @computed get appearanceEditor() {
         return <div className="appearance-editor">
             {this.widthAndDash}
-- 
cgit v1.2.3-70-g09d2


From b317845a0aa01319ba0b6d45a0f61d8fa2075e3f Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Sat, 1 Aug 2020 15:39:15 -0500
Subject: UI changes

---
 src/client/views/MainView.tsx                           |  2 +-
 src/client/views/collections/CollectionDockingView.scss | 14 +++++++++++---
 src/client/views/collections/CollectionMenu.tsx         |  1 +
 .../collections/collectionFreeForm/PropertiesView.scss  | 17 ++++++++---------
 .../collections/collectionFreeForm/PropertiesView.tsx   |  8 ++++----
 5 files changed, 25 insertions(+), 17 deletions(-)

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

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 993c6f4b6..d095a9836 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -172,7 +172,7 @@ export class MainView extends React.Component {
             fa.faFillDrip, fa.faLink, fa.faUnlink, fa.faBold, fa.faItalic, fa.faChevronLeft, fa.faUnderline, fa.faStrikethrough, fa.faSuperscript, fa.faSubscript,
             fa.faIndent, fa.faEyeDropper, fa.faPaintRoller, fa.faBars, fa.faBrush, fa.faShapes, fa.faEllipsisH, fa.faHandPaper, fa.faMap, fa.faUser, faHireAHelper,
             fa.faDesktop, fa.faTrashRestore, fa.faUsers, fa.faWrench, fa.faCog, fa.faMap, fa.faBellSlash, fa.faExpandAlt, fa.faArchive, fa.faBezierCurve, fa.faCircle,
-            fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, faBuffer, fa.faExpand, fa.faUndo);
+            fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, faBuffer, fa.faExpand, fa.faUndo, fa.faSlidersH);
         this.initEventListeners();
         this.initAuthenticationRouters();
     }
diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss
index 6d894b56a..27d66f796 100644
--- a/src/client/views/collections/CollectionDockingView.scss
+++ b/src/client/views/collections/CollectionDockingView.scss
@@ -12,12 +12,14 @@
         width: 100%;
         height: 100%;
         position: absolute;
+
         .miniThumb {
             background: #25252525;
             position: absolute;
         }
     }
 }
+
 .lm_title {
     margin-top: 3px;
     border-radius: 5px;
@@ -27,6 +29,7 @@
     transform: translate(0px, -3px);
     cursor: grab;
 }
+
 .lm_title.focus-visible {
     cursor: text;
 }
@@ -35,8 +38,9 @@
     overflow: hidden;
     height: 19px;
     margin-top: -2px;
-    display:inline-block;
+    display: inline-block;
 }
+
 .lm_active .lm_title {
     border: solid 1px lightgray;
 }
@@ -47,11 +51,11 @@
 }
 
 .lm_header .lm_tab {
-    padding-right : 20px;
+    padding-right: 20px;
 }
 
 .lm_popout {
-    display:none;
+    display: none;
 }
 
 .messageCounter {
@@ -74,6 +78,7 @@
     position: absolute;
     top: 0;
     left: 0;
+
     // overflow: hidden;  // bcz: menus don't show up when this is on (e.g., the parentSelectorMenu)
     .collectionDockingView-gear {
         padding-left: 5px;
@@ -81,7 +86,10 @@
         width: 18px;
         display: inline-block;
         margin: auto;
+
+        display: none;
     }
+
     .collectionDockingView-dragAsDocument {
         touch-action: none;
         position: absolute;
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 498030b71..fdd1b4e81 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -415,6 +415,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
     miniMap = (): void => {
         this.document.hideMinimap = !this.document.hideMinimap;
     }
+
     private _palette = ["#D0021B", "#F5A623", "#F8E71C", "#8B572A", "#7ED321", "#417505", "#9013FE", "#4A90E2", "#50E3C2", "#B8E986", "#000000", "#4A4A4A", "#9B9B9B", "#FFFFFF", ""];
     private _width = ["1", "5", "10", "100"];
     // private _draw = ["⎯", "→", "↔︎", "∿", "↝", "↭", "ロ", "O", "∆"];
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index 8847fe89d..74f32275a 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -14,18 +14,17 @@
         padding-top: 12px;
         padding-bottom: 12px;
         display: flex;
-
-        .propertiesView-title-name {
-            font-size: 18px;
-            font-weight: bold;
-            padding-left: 45px;
-        }
+        font-size: 18px;
+        font-weight: bold;
+        justify-content: center;
 
         .propertiesView-title-icon {
             width: 20px;
             height: 20px;
             padding-left: 38px;
             margin-top: -5px;
+            right: 19;
+            position: absolute;
 
             &:hover {
                 color: grey;
@@ -580,7 +579,7 @@
             margin-right: 35px;
 
             .arrows-head-title {
-                font-size: 12;
+                font-size: 10;
             }
 
             .arrows-head-input {
@@ -593,7 +592,7 @@
             display: flex;
 
             .arrows-tail-title {
-                font-size: 12;
+                font-size: 10;
             }
 
             .arrows-tail-input {
@@ -610,7 +609,7 @@
         margin-bottom: 6px;
 
         .dashed-title {
-            font-size: 12;
+            font-size: 10;
         }
 
         .dashed-input {
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index f39a75b81..3eb3ef8ab 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -115,7 +115,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
             const rows: JSX.Element[] = [];
             for (const key of Object.keys(ids).slice().sort()) {
                 const contents = doc[key];
-                if (contents === "UNDEFINED") {
+                if (key[0] === "#") {
                     rows.push(<div style={{ display: "flex", overflowY: "visible", marginBottom: "2px" }} key={key}>
                         <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key}</span>
                     &nbsp;
@@ -158,7 +158,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
             for (const key of Object.keys(ids).slice().sort()) {
                 if (key[0] === key[0].toUpperCase() || key[0] === "#" || key === "author" || key === "creationDate" || key.indexOf("lastModified") !== -1) {
                     const contents = doc[key];
-                    if (contents === "UNDEFINED") {
+                    if (key[0] === "#") {
                         rows.push(<div className="uneditable-field" key={key}>
                             <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key}</span>
                     &nbsp;
@@ -211,7 +211,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 KeyValueBox.SetField(doc, newVal.substring(0, newVal.indexOf(":")), newVal.substring(newVal.indexOf(":") + 1, newVal.length), true);
                 return true;
             } else if (value[0] === "#") {
-                const newVal = value + ":'UNDEFINED'";
+                const newVal = value + `:'${value}'`;
                 KeyValueBox.SetField(doc, newVal.substring(0, newVal.indexOf(":")), newVal.substring(newVal.indexOf(":") + 1, newVal.length), true);
                 return true;
             }
@@ -745,7 +745,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
         return <div className="propertiesView" style={{ width: this.props.width }} >
             <div className="propertiesView-title" style={{ width: this.props.width }}>
-                <div className="propertiesView-title-name">Properties </div>
+                Properties
                 <div className="propertiesView-title-icon" onPointerDown={this.props.onDown}>
                     <FontAwesomeIcon icon="times" color="black" size="sm" />
                 </div>
-- 
cgit v1.2.3-70-g09d2


From 5bbfed1556e47546eb6768681a86859b011a4c18 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Sun, 2 Aug 2020 13:55:38 -0500
Subject: sharing fix

---
 src/client/util/SharingManager.tsx                               | 4 ++--
 .../views/collections/collectionFreeForm/PropertiesView.scss     | 6 +++---
 .../views/collections/collectionFreeForm/PropertiesView.tsx      | 9 ++++++---
 3 files changed, 11 insertions(+), 8 deletions(-)

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

diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index eda12a5e9..7a0fe4140 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -142,7 +142,7 @@ export default class SharingManager extends React.Component<{}> {
      * @param group 
      * @param permission 
      */
-    setInternalGroupSharing = (group: Doc, permission: string) => {
+    setInternalGroupSharing = (group: Doc, permission: string, targetDoc?: Doc) => {
         const members: string[] = JSON.parse(StrCast(group.members));
         const users: ValidatedUser[] = this.users.filter(({ user: { email } }) => members.includes(email));
 
@@ -224,7 +224,7 @@ export default class SharingManager extends React.Component<{}> {
         }
     }
 
-    setInternalSharing = (recipient: ValidatedUser, permission: string) => {
+    setInternalSharing = (recipient: ValidatedUser, permission: string, targetDoc?: Doc) => {
         const { user, notificationDoc } = recipient;
         const target = targetDoc || this.targetDoc!;
         const key = user.email.replace('.', '_');
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index 74f32275a..a96716659 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -241,7 +241,7 @@
 
             .propertiesView-sharingTable-item-name {
                 font-weight: bold;
-                width: 80px;
+                width: 95px;
                 overflow-x: hidden;
                 display: inline-block;
                 text-overflow: ellipsis;
@@ -259,8 +259,8 @@
                     border: none;
                     background-color: inherit;
                     width: 75px;
-                    text-align: justify; // for Edge
-                    text-align-last: end;
+                    //text-align: justify; // for Edge
+                    //text-align-last: end;
 
                     &:hover {
                         cursor: pointer;
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 3eb3ef8ab..73f0f1bdd 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -156,7 +156,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
             doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key));
             const rows: JSX.Element[] = [];
             for (const key of Object.keys(ids).slice().sort()) {
-                if (key[0] === key[0].toUpperCase() || key[0] === "#" || key === "author" || key === "creationDate" || key.indexOf("lastModified") !== -1) {
+                if ((key[0] === key[0].toUpperCase() && key.substring(0, 3) !== "ACL")
+                    || key[0] === "#" || key === "author" ||
+                    key === "creationDate" || key.indexOf("lastModified") !== -1) {
+
                     const contents = doc[key];
                     if (key[0] === "#") {
                         rows.push(<div className="uneditable-field" key={key}>
@@ -297,8 +300,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     sharingItem(name: string, effectiveAcl: symbol, permission?: string) {
         return <div className="propertiesView-sharingTable-item">
-            <div className="propertiesView-sharingTable-item-name" style={{ width: name !== "Me" ? "70px" : "80px" }}> {name} </div>
-            {name !== "Me" ? this.notifyIcon : null}
+            <div className="propertiesView-sharingTable-item-name" style={{ width: name !== "Me" ? "85px" : "80px" }}> {name} </div>
+            {/* {name !== "Me" ? this.notifyIcon : null} */}
             <div className="propertiesView-sharingTable-item-permission">
                 {effectiveAcl === AclAdmin && permission !== "Owner" ? this.getPermissionsSelect(name) : permission}
                 {permission === "Owner" ? this.expansionIcon : null}
-- 
cgit v1.2.3-70-g09d2


From 8303cd6389fe9e3c861d7b429bb4e32d3417a895 Mon Sep 17 00:00:00 2001
From: Geireann Lindfield Roberts <60007097+geireann@users.noreply.github.com>
Date: Mon, 3 Aug 2020 02:58:31 +0800
Subject: Merge remote-tracking branch 'origin/menu_restructure' into
 presentation_updates

---
 package.json                                       |   6 +-
 src/Utils.ts                                       |   4 +-
 src/client/documents/DocumentTypes.ts              |   1 +
 src/client/documents/Documents.ts                  |  12 +
 src/client/util/CurrentUserUtils.ts                | 116 ++-
 src/client/util/GroupMemberView.scss               |   2 +-
 src/client/util/SelectionManager.ts                |   3 +
 src/client/util/SharingManager.tsx                 |   6 +-
 src/client/views/ContextMenuItem.tsx               |   4 +-
 src/client/views/DocumentButtonBar.tsx             |   8 +-
 src/client/views/DocumentDecorations.tsx           |  19 +-
 src/client/views/EditableView.tsx                  |   2 +-
 src/client/views/MainView.scss                     | 135 +++-
 src/client/views/MainView.tsx                      | 393 ++++++----
 src/client/views/PreviewCursor.tsx                 |   6 +-
 src/client/views/PropertiesButtons.scss            | 119 +++
 src/client/views/PropertiesButtons.tsx             | 598 ++++++++++++++
 .../views/collections/CollectionDockingView.scss   |  16 +-
 .../views/collections/CollectionDockingView.tsx    |  20 +-
 src/client/views/collections/CollectionMenu.tsx    |  79 +-
 .../views/collections/CollectionSchemaView.tsx     |   2 +-
 .../views/collections/CollectionStackingView.tsx   |   1 +
 .../CollectionStackingViewFieldColumn.tsx          |   2 +-
 src/client/views/collections/CollectionSubView.tsx |   2 +-
 .../views/collections/CollectionTreeView.tsx       |   7 +-
 src/client/views/collections/CollectionView.scss   |   1 +
 src/client/views/collections/CollectionView.tsx    |  11 +-
 .../views/collections/ParentDocumentSelector.tsx   |   6 +-
 src/client/views/collections/SchemaTable.tsx       |   8 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  12 +-
 .../collectionFreeForm/FormatShapePane.tsx         |  27 +-
 .../collectionFreeForm/PropertiesView.scss         | 620 +++++++++++++++
 .../collectionFreeForm/PropertiesView.tsx          | 858 +++++++++++++++++++++
 src/client/views/linking/LinkMenuItem.tsx          |   3 +-
 .../views/nodes/ContentFittingDocumentView.tsx     |   3 +
 src/client/views/nodes/DocumentContentsView.tsx    |   3 +-
 src/client/views/nodes/DocumentLinksButton.tsx     |   5 +-
 src/client/views/nodes/DocumentView.tsx            |  62 +-
 src/client/views/nodes/FieldView.tsx               |   1 +
 src/client/views/nodes/FontIconBox.scss            |   2 +-
 src/client/views/nodes/MenuIconBox.scss            |  49 ++
 src/client/views/nodes/MenuIconBox.tsx             |  33 +
 src/client/views/nodes/PresBox.tsx                 |  10 +-
 .../views/nodes/formattedText/DashFieldView.tsx    |   2 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |   4 +-
 .../views/nodes/formattedText/RichTextMenu.tsx     |  41 +-
 src/client/views/nodes/formattedText/nodes_rts.ts  |   8 +-
 src/fields/Doc.ts                                  |   6 +-
 src/server/ActionUtilities.ts                      |  10 +-
 src/server/ApiManagers/UtilManager.ts              |   1 -
 src/server/DashUploadUtils.ts                      |  27 +-
 src/server/GarbageCollector.ts                     |   6 +-
 src/server/MemoryDatabase.ts                       |   5 +-
 src/server/Message.ts                              |   2 +-
 src/server/ProcessFactory.ts                       |   6 +-
 src/server/Recommender.ts                          | 133 ----
 src/server/RouteManager.ts                         |   8 +-
 src/server/Search.ts                               |   2 +-
 src/server/database.ts                             |   8 +-
 src/server/downsize.ts                             |   2 +-
 src/server/index.ts                                |  34 +-
 src/server/server_Initialization.ts                |  38 +-
 src/server/websocket.ts                            |  27 +-
 63 files changed, 3126 insertions(+), 521 deletions(-)
 create mode 100644 src/client/views/PropertiesButtons.scss
 create mode 100644 src/client/views/PropertiesButtons.tsx
 create mode 100644 src/client/views/collections/collectionFreeForm/PropertiesView.scss
 create mode 100644 src/client/views/collections/collectionFreeForm/PropertiesView.tsx
 create mode 100644 src/client/views/nodes/MenuIconBox.scss
 create mode 100644 src/client/views/nodes/MenuIconBox.tsx
 delete mode 100644 src/server/Recommender.ts

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

diff --git a/package.json b/package.json
index 11af6b2c6..420765e7c 100644
--- a/package.json
+++ b/package.json
@@ -11,8 +11,8 @@
     },
     "scripts": {
         "start-release": "cross-env RELEASE=true 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 --transpile-only -- src/server/index.ts",
-        "oldstart": "cross-env 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 --debug --transpile-only  -- src/server/index.ts",
+        "oldstart": "cross-env NODE_OPTIONS=--max_old_space_size=4096 ts-node-dev --debug -- src/server/index.ts",
         "debug": "cross-env NODE_OPTIONS=--max_old_space_size=8192 ts-node-dev --transpile-only --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",
@@ -260,4 +260,4 @@
         "xoauth2": "^1.2.0",
         "xregexp": "^4.3.0"
     }
-}
+}
\ No newline at end of file
diff --git a/src/Utils.ts b/src/Utils.ts
index a01a94134..0b057dc23 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -1,8 +1,8 @@
 import v4 = require('uuid/v4');
 import v5 = require("uuid/v5");
-import { Socket, Room } from 'socket.io';
-import { Message } from './server/Message';
 import { ColorState } from 'react-color';
+import { Socket } from 'socket.io';
+import { Message } from './server/Message';
 
 export namespace Utils {
     export let DRAG_THRESHOLD = 4;
diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts
index 985fcce11..659f78970 100644
--- a/src/client/documents/DocumentTypes.ts
+++ b/src/client/documents/DocumentTypes.ts
@@ -13,6 +13,7 @@ export enum DocumentType {
     INK = "ink",        // ink stroke
     SCREENSHOT = "screenshot",  // view of a desktop application
     FONTICON = "fonticonbox",   // font icon
+    MENUICON = "menuiconbox",
     QUERY = "query",            // search query
     LABEL = "label",            // simple text label
     BUTTON = "button",          // onClick button
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 0da93aa7a..01cdb1eee 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -31,6 +31,7 @@ import { ColorBox } from "../views/nodes/ColorBox";
 import { ComparisonBox } from "../views/nodes/ComparisonBox";
 import { DocHolderBox } from "../views/nodes/DocHolderBox";
 import { FontIconBox } from "../views/nodes/FontIconBox";
+import { MenuIconBox } from "../views/nodes/MenuIconBox";
 import { FormattedTextBox } from "../views/nodes/formattedText/FormattedTextBox";
 import { ImageBox } from "../views/nodes/ImageBox";
 import { KeyValueBox } from "../views/nodes/KeyValueBox";
@@ -305,6 +306,13 @@ export namespace Docs {
                 layout: { view: FontIconBox, dataField: defaultDataKey },
                 options: { _width: 40, _height: 40, borderRounding: "100%" },
             }],
+            [DocumentType.MENUICON, {
+                layout: { view: MenuIconBox, dataField: defaultDataKey },
+            }],
+            // [DocumentType.RECOMMENDATION, {
+            //     layout: { view: RecommendationsBox, dataField: defaultDataKey },
+            //     options: { _width: 200, _height: 200 },
+            // }],
             [DocumentType.WEBCAM, {
                 layout: { view: DashWebRTCVideo, dataField: defaultDataKey }
             }],
@@ -791,6 +799,10 @@ export namespace Docs {
             return InstanceFromProto(Prototypes.get(DocumentType.FONTICON), undefined, { hideLinkButton: true, ...(options || {}) });
         }
 
+        export function MenuIconDocument(options?: DocumentOptions) {
+            return InstanceFromProto(Prototypes.get(DocumentType.MENUICON), undefined, { hideLinkButton: true, ...(options || {}) });
+        }
+
         export function PresElementBoxDocument(options?: DocumentOptions) {
             return InstanceFromProto(Prototypes.get(DocumentType.PRESELEMENT), undefined, { ...(options || {}) });
         }
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 6d752832a..b37c91c56 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -38,6 +38,16 @@ export class CurrentUserUtils {
     @observable public static GuestWorkspace: Doc | undefined;
     @observable public static GuestMobile: Doc | undefined;
 
+    @observable public static toolsBtn: any | undefined;
+    @observable public static libraryBtn: any | undefined;
+    @observable public static searchBtn: any | undefined;
+
+    @observable public static toolsStack: any | undefined;
+    @observable public static workspaceStack: any | undefined;
+    @observable public static catalogStack: any | undefined;
+    @observable public static closedStack: any | undefined;
+    @observable public static searchStack: any | undefined;
+
     // sets up the default User Templates - slideView, queryView, descriptionView
     static setupUserTemplateButtons(doc: Doc) {
         if (doc["template-button-query"] === undefined) {
@@ -492,6 +502,46 @@ export class CurrentUserUtils {
         return doc.myItemCreators as Doc;
     }
 
+    static menuBtnDescriptions(): {
+        title: string, icon: string, click: string,
+    }[] {
+        return [
+            { title: "Workspace", icon: "desktop", click: 'scriptContext.selectMenu("Workspace")' },
+            { title: "Catalog", icon: "file", click: 'scriptContext.selectMenu("Catalog")' },
+            { title: "Archive", icon: "archive", click: 'scriptContext.selectMenu("Archive")' },
+            { title: "Import", icon: "upload", click: 'scriptContext.selectMenu("Import")' },
+            { title: "Sharing", icon: "users", click: 'scriptContext.selectMenu("Sharing")' },
+            { title: "Tools", icon: "wrench", click: 'scriptContext.selectMenu("Tools")' },
+            { title: "Help", icon: "question-circle", click: 'scriptContext.selectMenu("Help")' },
+            { title: "Settings", icon: "cog", click: 'scriptContext.selectMenu("Settings")' },
+        ];
+    }
+
+    static setupMenuPanel(doc: Doc) {
+        if (doc.menuStack === undefined) {
+            const buttons = CurrentUserUtils.menuBtnDescriptions();
+            const menuBtns = buttons.map(({ title, icon, click }) => Docs.Create.MenuIconDocument({
+                icon,
+                title,
+                _backgroundColor: "black",
+                stayInCollection: true,
+                _width: 60,
+                _height: 60,
+                onClick: ScriptField.MakeScript(click, { scriptContext: "any" }),
+            }));
+
+            doc.menuStack = new PrefetchProxy(Docs.Create.StackingDocument(menuBtns, {
+                title: "menuItemPanel",
+                _backgroundColor: "black",
+                _gridGap: 0,
+                _yMargin: 0,
+                _yPadding: 0, _xMargin: 0, _autoHeight: false, _width: 60, _columnWidth: 60, lockedPosition: true, _chromeStatus: "disabled",
+            }));
+        }
+        return doc.menuStack as Doc;
+    }
+
+
     // Sets up mobile menu if it is undefined creates a new one, otherwise returns existing menu
     static setupActiveMobileMenu(doc: Doc) {
         if (doc.activeMobileMenu === undefined) {
@@ -601,6 +651,8 @@ export class CurrentUserUtils {
         const creatorBtns = await CurrentUserUtils.setupCreatorButtons(doc);
         const templateBtns = CurrentUserUtils.setupUserTemplateButtons(doc);
 
+        doc["tabs-button-tools"] = undefined;
+
         if (doc.myCreators === undefined) {
             doc.myCreators = new PrefetchProxy(Docs.Create.StackingDocument([creatorBtns, templateBtns], {
                 title: "all Creators", _yMargin: 0, _autoHeight: true, _xMargin: 0,
@@ -617,8 +669,11 @@ export class CurrentUserUtils {
 
         if (doc["tabs-button-tools"] === undefined) {
             const toolsStack = new PrefetchProxy(Docs.Create.StackingDocument([doc.myCreators as Doc, doc.myColorPicker as Doc], {
-                _width: 500, lockedPosition: true, _chromeStatus: "disabled", title: "tools stack", forceActive: true
+                _width: 500, lockedPosition: true, _chromeStatus: "disabled", hideFilterView: true, title: "tools stack", forceActive: true
             })) as any as Doc;
+
+            CurrentUserUtils.toolsStack = toolsStack;
+
             doc["tabs-button-tools"] = new PrefetchProxy(Docs.Create.ButtonDocument({
                 _width: 35, _height: 25, title: "Tools", _fontSize: "10pt",
                 letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)",
@@ -627,41 +682,63 @@ export class CurrentUserUtils {
                 dragFactory: toolsStack,
                 removeDropProperties: new List<string>(["lockedPosition"]),
                 stayInCollection: true,
+                hideFilterView: true,
                 targetContainer: new PrefetchProxy(sidebarContainer) as any as Doc,
                 onClick: ScriptField.MakeScript("this.targetContainer.proto = this.sourcePanel"),
             }));
         }
-        (doc["tabs-button-tools"] as Doc).sourcePanel; // prefetch sourcePanel
-        return doc["tabs-button-tools"] as Doc;
+        (doc["tabs-button-tools"] as any as Doc).sourcePanel; // prefetch sourcePanel
+
+        return doc["tabs-button-tools"] as any as Doc;
     }
 
     static setupWorkspaces(doc: Doc) {
         // setup workspaces library item
+        doc.myWorkspaces === undefined;
         if (doc.myWorkspaces === undefined) {
             doc.myWorkspaces = new PrefetchProxy(Docs.Create.TreeDocument([], {
-                title: "WORKSPACES", _height: 100, forceActive: true, boxShadow: "0 0", lockedPosition: true,
+                title: "WORKSPACES", _height: 100, forceActive: true, boxShadow: "0 0", lockedPosition: true, treeViewOpen: true,
             }));
         }
         const newWorkspace = ScriptField.MakeScript(`createNewWorkspace()`);
         (doc.myWorkspaces as Doc).contextMenuScripts = new List<ScriptField>([newWorkspace!]);
         (doc.myWorkspaces as Doc).contextMenuLabels = new List<string>(["Create New Workspace"]);
 
+        const workspaces = doc.myWorkspaces as Doc;
+
+        CurrentUserUtils.workspaceStack = new PrefetchProxy(Docs.Create.TreeDocument([workspaces], {
+            title: " ", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias",
+            treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, treeViewOpen: true,
+            lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same"
+        })) as any as Doc;
+
         return doc.myWorkspaces as Doc;
     }
     static setupCatalog(doc: Doc) {
+        doc.myCatalog === undefined;
         if (doc.myCatalog === undefined) {
             doc.myCatalog = new PrefetchProxy(Docs.Create.SchemaDocument([], [], {
                 title: "CATALOG", _height: 1000, _fitWidth: true, forceActive: true, boxShadow: "0 0", treeViewPreventOpen: false,
-                childDropAction: "alias", targetDropAction: "same", stayInCollection: true,
+                childDropAction: "alias", targetDropAction: "same", stayInCollection: true, treeViewOpen: true,
             }));
         }
+
+        const catalog = doc.myCatalog as Doc;
+
+        CurrentUserUtils.catalogStack = new PrefetchProxy(Docs.Create.TreeDocument([catalog], {
+            title: " ", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias",
+            treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, treeViewOpen: true,
+            lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same"
+        })) as any as Doc;
+
         return doc.myCatalog as Doc;
     }
     static setupRecentlyClosed(doc: Doc) {
         // setup Recently Closed library item
+        doc.myRecentlyClosed === undefined;
         if (doc.myRecentlyClosed === undefined) {
             doc.myRecentlyClosed = new PrefetchProxy(Docs.Create.TreeDocument([], {
-                title: "RECENTLY CLOSED", _height: 75, forceActive: true, boxShadow: "0 0", treeViewPreventOpen: true, stayInCollection: true,
+                title: "RECENTLY CLOSED", _height: 75, forceActive: true, boxShadow: "0 0", treeViewPreventOpen: false, treeViewOpen: true, stayInCollection: true,
             }));
         }
         // this is equivalent to using PrefetchProxies to make sure the recentlyClosed doc is ready
@@ -670,6 +747,14 @@ export class CurrentUserUtils {
         (doc.myRecentlyClosed as Doc).contextMenuScripts = new List<ScriptField>([clearAll!]);
         (doc.myRecentlyClosed as Doc).contextMenuLabels = new List<string>(["Clear All"]);
 
+        const recentlyClosed = doc.myRecentlyClosed as Doc;
+
+        CurrentUserUtils.closedStack = new PrefetchProxy(Docs.Create.TreeDocument([recentlyClosed], {
+            title: " ", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias",
+            treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false, treeViewOpen: true,
+            lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same"
+        })) as any as Doc;
+
         return doc.myRecentlyClosed as Doc;
     }
     // setup the Library button which will display the library panel.  This panel includes a collection of workspaces, documents, and recently closed views
@@ -681,7 +766,7 @@ export class CurrentUserUtils {
         if (doc["tabs-button-library"] === undefined) {
             const libraryStack = new PrefetchProxy(Docs.Create.TreeDocument([workspaces, documents, recentlyClosed, doc], {
                 title: "Library", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, childDropAction: "alias",
-                treeViewTruncateTitleWidth: 150,
+                treeViewTruncateTitleWidth: 150, hideFilterView: true, treeViewPreventOpen: false,
                 lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same"
             })) as any as Doc;
             doc["tabs-button-library"] = new PrefetchProxy(Docs.Create.ButtonDocument({
@@ -701,6 +786,7 @@ export class CurrentUserUtils {
 
     // setup the Search button which will display the search panel.
     static setupSearchBtnPanel(doc: Doc, sidebarContainer: Doc) {
+        doc["tabs-button-search"] = undefined;
         if (doc["tabs-button-search"] === undefined) {
             doc["tabs-button-search"] = new PrefetchProxy(Docs.Create.ButtonDocument({
                 _width: 50, _height: 25, title: "Search", _fontSize: "10pt",
@@ -711,8 +797,9 @@ export class CurrentUserUtils {
                 lockedPosition: true,
                 onClick: ScriptField.MakeScript("this.targetContainer.proto = this.sourcePanel")
             }));
+            CurrentUserUtils.searchStack = new PrefetchProxy(Docs.Create.QueryDocument({ title: "search stack", })) as any as Doc;
         }
-        return doc["tabs-button-search"] as Doc;
+        return doc["tabs-button-search"] as any as Doc;
     }
 
     static setupSidebarContainer(doc: Doc) {
@@ -728,17 +815,17 @@ export class CurrentUserUtils {
     // setup the list of sidebar mode buttons which determine what is displayed in the sidebar
     static async setupSidebarButtons(doc: Doc) {
         const sidebarContainer = CurrentUserUtils.setupSidebarContainer(doc);
-        const toolsBtn = await CurrentUserUtils.setupToolsBtnPanel(doc, sidebarContainer);
-        const libraryBtn = CurrentUserUtils.setupLibraryPanel(doc, sidebarContainer);
-        const searchBtn = CurrentUserUtils.setupSearchBtnPanel(doc, sidebarContainer);
+        CurrentUserUtils.toolsBtn = await CurrentUserUtils.setupToolsBtnPanel(doc, sidebarContainer);
+        CurrentUserUtils.libraryBtn = CurrentUserUtils.setupLibraryPanel(doc, sidebarContainer);
+        CurrentUserUtils.searchBtn = CurrentUserUtils.setupSearchBtnPanel(doc, sidebarContainer);
 
         // Finally, setup the list of buttons to display in the sidebar
         if (doc["tabs-buttons"] === undefined) {
-            doc["tabs-buttons"] = new PrefetchProxy(Docs.Create.StackingDocument([libraryBtn, searchBtn, toolsBtn], {
+            doc["tabs-buttons"] = new PrefetchProxy(Docs.Create.StackingDocument([CurrentUserUtils.libraryBtn, CurrentUserUtils.searchBtn, CurrentUserUtils.toolsBtn], {
                 _width: 500, _height: 80, boxShadow: "0 0", _pivotField: "title", _columnsHideIfEmpty: true, ignoreClick: true, _chromeStatus: "view-mode",
                 title: "sidebar btn row stack", backgroundColor: "dimGray",
             }));
-            (toolsBtn.onClick as ScriptField).script.run({ this: toolsBtn });
+            (CurrentUserUtils.toolsBtn.onClick as ScriptField).script.run({ this: CurrentUserUtils.toolsBtn });
         }
     }
 
@@ -749,7 +836,7 @@ export class CurrentUserUtils {
     })) as any as Doc
 
     static ficon = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({
-        ...opts, dropAction: "alias", removeDropProperties: new List<string>(["dropAction"]), _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100
+        ...opts, dropAction: "alias", removeDropProperties: new List<string>(["dropAction"]), _nativeWidth: 40, _nativeHeight: 40, _width: 40, _height: 40
     })) as any as Doc
 
     /// sets up the default list of buttons to be shown in the expanding button menu at the bottom of the Dash window
@@ -855,6 +942,7 @@ export class CurrentUserUtils {
         this.setupDocTemplates(doc); // sets up the template menu of templates
         this.setupRightSidebar(doc);  // sets up the right sidebar collection for mobile upload documents and sharing
         this.setupActiveMobileMenu(doc); // sets up the current mobile menu for Dash Mobile
+        this.setupMenuPanel(doc);
         this.setupOverlays(doc);  // documents in overlay layer
         this.setupDockedButtons(doc);  // the bottom bar of font icons
         this.setupDefaultPresentation(doc); // presentation that's initially triggered
diff --git a/src/client/util/GroupMemberView.scss b/src/client/util/GroupMemberView.scss
index 2fc27ed03..2eb164988 100644
--- a/src/client/util/GroupMemberView.scss
+++ b/src/client/util/GroupMemberView.scss
@@ -44,7 +44,7 @@
             background: none;
 
             &:hover {
-                text-overflow: visible;
+                text-overflow: unset;
                 overflow-x: auto;
             }
         }
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 20d881961..05ba00331 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -12,6 +12,7 @@ export namespace SelectionManager {
 
         @observable IsDragging: boolean = false;
         SelectedDocuments: ObservableMap<DocumentView, boolean> = new ObservableMap();
+
         @action
         SelectDoc(docView: DocumentView, ctrlPressed: boolean): void {
 
@@ -32,6 +33,7 @@ export namespace SelectionManager {
         }
         @action
         DeselectDoc(docView: DocumentView): void {
+
             if (manager.SelectedDocuments.get(docView)) {
                 manager.SelectedDocuments.delete(docView);
                 docView.props.whenActiveChanged(false);
@@ -40,6 +42,7 @@ export namespace SelectionManager {
         }
         @action
         DeselectAll(): void {
+
             Array.from(manager.SelectedDocuments.keys()).map(dv => dv.props.whenActiveChanged(false));
             manager.SelectedDocuments.clear();
             Doc.UserDoc().activeSelection = new List<Doc>([]);
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index 5896bdf92..000b3e46c 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -72,8 +72,6 @@ export default class SharingManager extends React.Component<{}> {
     @observable private showUserOptions: boolean = false; // whether to show individuals as options when sharing (in the react-select component)
     @observable private showGroupOptions: boolean = false; // // whether to show groups as options when sharing (in the react-select component)
 
-
-
     // private get linkVisible() {
     //     return this.sharingDoc ? this.sharingDoc[PublicKey] !== SharingPermissions.None : false;
     // }
@@ -148,7 +146,7 @@ export default class SharingManager extends React.Component<{}> {
         const members: string[] = JSON.parse(StrCast(group.members));
         const users: ValidatedUser[] = this.users.filter(({ user: { email } }) => members.includes(email));
 
-        const target = this.targetDoc!;
+        const target = targetDoc || this.targetDoc!;
         const ACL = `ACL-${StrCast(group.groupName)}`;
 
         target.author === Doc.CurrentUserEmail && distributeAcls(ACL, permission as SharingPermissions, target);
@@ -222,7 +220,7 @@ export default class SharingManager extends React.Component<{}> {
 
     setInternalSharing = (recipient: ValidatedUser, permission: string) => {
         const { user, notificationDoc } = recipient;
-        const target = this.targetDoc!;
+        const target = targetDoc || this.targetDoc!;
         const key = user.email.replace('.', '_');
         const ACL = `ACL-${key}`;
 
diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx
index 81432968d..7e233ec04 100644
--- a/src/client/views/ContextMenuItem.tsx
+++ b/src/client/views/ContextMenuItem.tsx
@@ -80,7 +80,7 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select
     render() {
         if ("event" in this.props) {
             return (
-                <div className={"contextMenu-item" + (this.props.selected ? " contextMenu-itemSelected" : "")} onClick={this.handleEvent}>
+                <div className={"contextMenu-item" + (this.props.selected ? " contextMenu-itemSelected" : "")} onPointerDown={this.handleEvent}>
                     {this.props.icon ? (
                         <span className="icon-background">
                             <FontAwesomeIcon icon={this.props.icon} size="sm" />
@@ -95,7 +95,7 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select
             const where = !this.overItem ? "" : this._overPosY < window.innerHeight / 3 ? "flex-start" : this._overPosY > window.innerHeight * 2 / 3 ? "flex-end" : "center";
             const marginTop = !this.overItem ? "" : this._overPosY < window.innerHeight / 3 ? "20px" : this._overPosY > window.innerHeight * 2 / 3 ? "-20px" : "";
             const submenu = !this.overItem ? (null) :
-                <div className="contextMenu-subMenu-cont" style={{ marginLeft: "25%", left: "0px", marginTop }}>
+                <div className="contextMenu-subMenu-cont" style={{ marginLeft: "90%", left: "0px", marginTop }}>
                     {this._items.map(prop => <ContextMenuItem {...prop} key={prop.description} closeMenu={this.props.closeMenu} />)}
                 </div>;
             if (!("noexpand" in this.props)) {
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 6b85616c2..23a3e1684 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -281,7 +281,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
             {DocumentLinksButton.StartLink ? <div className="documentButtonBar-button">
                 <DocumentLinksButton links={this.view0.allLinks} View={this.view0} AlwaysOn={true} InMenu={true} StartLink={false} />
             </div> : null}
-            <div className="documentButtonBar-button">
+            {/* <div className="documentButtonBar-button">
                 {this.templateButton}
             </div>
             <div className="documentButtonBar-button">
@@ -289,16 +289,16 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
             </div>
             <div className="documentButtonBar-button">
                 {this.contextButton}
-            </div>
+            </div> */}
             <div className="documentButtonBar-button">
                 {this.pinButton}
             </div>
-            <div className="documentButtonBar-button" style={{ display: !considerPush ? "none" : "" }}>
+            {/* <div className="documentButtonBar-button" style={{ display: !considerPush ? "none" : "" }}>
                 {this.considerGoogleDocsPush}
             </div>
             <div className="documentButtonBar-button" style={{ display: !considerPull ? "none" : "" }}>
                 {this.considerGoogleDocsPull}
-            </div>
+            </div> */}
         </div>;
     }
 }
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 7fc4a5c99..dd5303904 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -1,5 +1,5 @@
 import { IconProp, library } from '@fortawesome/fontawesome-svg-core';
-import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote, faTextHeight, faArrowAltCircleDown, faArrowAltCircleUp, faCheckCircle, faCloudUploadAlt, faLink, faShare, faStopCircle, faSyncAlt, faTag, faTimes, faAngleLeft, faAngleRight, faAngleDoubleLeft, faAngleDoubleRight, faPause } from '@fortawesome/free-solid-svg-icons';
+import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote, faTextHeight, faArrowAltCircleDown, faArrowAltCircleUp, faCheckCircle, faCloudUploadAlt, faLink, faShare, faStopCircle, faSyncAlt, faTag, faTimes, faAngleLeft, faAngleRight, faAngleDoubleLeft, faAngleDoubleRight, faPause, faExternalLinkAlt } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { action, computed, observable, reaction, runInAction, get } from "mobx";
 import { observer } from "mobx-react";
@@ -47,6 +47,7 @@ library.add(faAngleDoubleRight);
 library.add(faAngleLeft);
 library.add(faAngleRight);
 library.add(faPause);
+library.add(faExternalLinkAlt);
 
 @observer
 export class DocumentDecorations extends React.Component<{}, { value: string }> {
@@ -533,12 +534,12 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 const ink = Cast(doc.data, InkField)?.inkData;
                 if (ink) {
                     const newPoints: { X: number, Y: number }[] = [];
-                    for (var i = 0; i < ink.length; i++) {
+                    ink.forEach(i => {
                         // (new x — oldx) + (oldxpoint * newWidt)/oldWidth 
-                        const newX = (doc.x - this._inkDocs[index].x) + (ink[i].X * doc._width) / this._inkDocs[index].width;
-                        const newY = (doc.y - this._inkDocs[index].y) + (ink[i].Y * doc._height) / this._inkDocs[index].height;
+                        const newX = ((doc.x || 0) - this._inkDocs[index].x) + (i.X * (doc._width || 0)) / this._inkDocs[index].width;
+                        const newY = ((doc.y || 0) - this._inkDocs[index].y) + (i.Y * (doc._height || 0)) / this._inkDocs[index].height;
                         newPoints.push({ X: newX, Y: newY });
-                    }
+                    });
                     doc.data = new InkField(newPoints);
 
                 }
@@ -617,9 +618,9 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                 </div>}
             </> :
             <>
-                {minimal ? (null) : <Tooltip title={<><div className="dash-tooltip">Show context menu</div></>} placement="top"><div className="documentDecorations-contextMenu" key="menu" onPointerDown={this.onSettingsDown}>
-                    <FontAwesomeIcon size="lg" icon="cog" />
-                </div></Tooltip>}
+                {/* {minimal ? (null) : <Tooltip title={<><div className="dash-tooltip">Show context menu</div></>} placement="top"><div className="documentDecorations-contextMenu" key="menu" onPointerDown={this.onSettingsDown}>
+                    <FontAwesomeIcon size="lg" icon="bars" />
+                </div></Tooltip>} */}
                 <div className="documentDecorations-title" key="title" onPointerDown={this.onTitleDown} >
                     <span style={{ width: "100%", display: "inline-block", cursor: "move" }}>{`${this.selectionTitle}`}</span>
                 </div>
@@ -666,7 +667,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                                 {"_"}
                             </div></Tooltip>}
                     <Tooltip title={<><div className="dash-tooltip">Open Document In Tab</div></>} placement="top"><div className="documentDecorations-openInTab" onPointerDown={this.onMaximizeDown}>
-                        {SelectionManager.SelectedDocuments().length === 1 ? DocumentDecorations.DocumentIcon(StrCast(seldoc.props.Document.layout, "...")) : "..."}
+                        {SelectionManager.SelectedDocuments().length === 1 ? <FontAwesomeIcon icon="external-link-alt" className="documentView-minimizedIcon" /> : "..."}
                     </div></Tooltip>
                     <div id="documentDecorations-rotation" className="documentDecorations-rotation"
                         onPointerDown={this.onRotateDown}> ⟲ </div>
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index c7b149842..f9d060681 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -191,7 +191,7 @@ export class EditableView extends React.Component<EditableProps> {
             return (this.props.contents instanceof ObjectField ? (null) :
                 <div className={`editableView-container-editing${this.props.oneLine ? "-oneLine" : ""}`}
                     ref={this._ref}
-                    style={{ display: this.props.display, minHeight: "20px", height: `${this.props.height ? this.props.height : "auto"}`, maxHeight: `${this.props.maxHeight}` }}
+                    style={{ display: this.props.display, minHeight: "17px", whiteSpace: "nowrap", height: `${this.props.height ? this.props.height : "auto"}`, maxHeight: `${this.props.maxHeight}` }}
                     onClick={this.onClick} placeholder={this.props.placeholder}>
                     <span style={{
                         fontStyle: this.props.fontStyle, fontSize: this.props.fontSize,
diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index e1ddbc533..054a409df 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -102,6 +102,44 @@
     user-select: none;
 }
 
+.mainView-propertiesDragger {
+    background-color: rgb(140, 139, 139);
+    height: 55px;
+    width: 15.5px;
+    position: absolute;
+    top: 55%;
+    border: 1px black solid;
+    border-radius: 0;
+    border-top-left-radius: 10px;
+    border-bottom-left-radius: 10px;
+    border-right: unset;
+    z-index: 2;
+
+    .mainView-propertiesDragger-icon {
+        width: 10px;
+        height: 10px;
+        float: left;
+        margin-left: 3px;
+        padding-top: 19px;
+    }
+
+    &:hover {
+        cursor: grab;
+    }
+}
+
+.mainiView-propertiesView {
+    display: flex;
+    flex-direction: column;
+    height: 100%;
+    position: absolute;
+    right: 0;
+    top: 0;
+    border-left: solid 1px;
+    z-index: 100000;
+    cursor: auto;
+}
+
 .mainView-flyoutContainer {
     display: flex;
     flex-direction: column;
@@ -114,6 +152,75 @@
     }
 }
 
+.mainView-menuPanel {
+
+    width: 60px;
+    background-color: black;
+    height: 100%;
+    //overflow-y: scroll;
+    //overflow-x: hidden;
+
+
+    .mainView-menuPanel-button {
+        padding: 7px;
+        padding-left: 7px;
+        width: 100%;
+
+        .mainView-menuPanel-button-wrap {
+            width: 45px;
+            /* padding: 5px; */
+            touch-action: none;
+            background: black;
+            transform-origin: top left;
+            /* margin-bottom: 5px; */
+            margin-top: 5px;
+            margin-right: 25px;
+            border-radius: 8px;
+
+            &:hover {
+                background: rgb(61, 61, 61);
+                cursor: pointer;
+            }
+        }
+    }
+
+    .mainView-menuPanel-button-label {
+        color: white;
+        margin-left: px;
+        margin-right: 4px;
+        border-radius: 8px;
+        width: 42px;
+        position: relative;
+        text-align: center;
+        font-size: 8px;
+        margin-top: 1px;
+        letter-spacing: normal;
+        padding: 3px;
+        background-color: inherit;
+    }
+
+    .mainView-menuPanel-button-icon {
+        width: auto;
+        height: 35px;
+        padding: 5px;
+    }
+
+    svg {
+        width: 95% !important;
+        height: 95%;
+    }
+}
+
+.mainView-searchPanel {
+    width: 100%;
+    height: 33px;
+    background-color: black;
+    color: white;
+    text-align: center;
+    vertical-align: middle;
+    padding-top: 6px;
+}
+
 .mainView-mainDiv {
     width: 100%;
     height: 100%;
@@ -162,26 +269,44 @@
     display: flex;
     flex-direction: column;
     z-index: 2;
+
+    .mainView-libraryFlyout-close {
+        right: 6;
+        top: 5;
+        position: absolute;
+        margin-right: 6px;
+        z-index: 10;
+        margin-bottom: 10;
+    }
 }
 
 .mainView-expandFlyoutButton {
     position: absolute;
-    top: 100px;
-    right: 30px;
+    top: 120px;
+    right: 55px;
     cursor: pointer;
 }
 
 .mainView-libraryHandle {
-    width: 20px;
+    width: 28px;
     left: calc(100% - 10px);
-    height: 40px;
+    height: 55px;
     top: 50%;
     border: 1px solid black;
-    border-radius: 5px;
+    border-radius: 8px;
     position: absolute;
     z-index: 2;
     touch-action: none;
     cursor: ew-resize;
+
+    .mainView-libraryHandle-icon {
+        width: 10px;
+        height: 10px;
+        float: right;
+        margin-right: 3px;
+        padding-top: 19px;
+    }
+
 }
 
 .mainView-workspace {
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 58478ce92..54b57a887 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -1,7 +1,6 @@
 import { library } from '@fortawesome/fontawesome-svg-core';
 import { faHireAHelper, faBuffer } from '@fortawesome/free-brands-svg-icons';
 import * as fa from '@fortawesome/free-solid-svg-icons';
-import { ANTIMODEMENU_HEIGHT } from './globalCssVariables.scss';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, configure, observable, reaction, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
@@ -12,51 +11,55 @@ import { Doc, DocListCast, Field, Opt } from '../../fields/Doc';
 import { Id } from '../../fields/FieldSymbols';
 import { List } from '../../fields/List';
 import { listSpec } from '../../fields/Schema';
+import { ScriptField } from '../../fields/ScriptField';
 import { BoolCast, Cast, FieldValue, StrCast } from '../../fields/Types';
 import { TraceMobx } from '../../fields/util';
-import { CurrentUserUtils } from '../util/CurrentUserUtils';
-import { emptyFunction, emptyPath, returnFalse, returnOne, returnZero, returnTrue, Utils, returnEmptyFilter } from '../../Utils';
+import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnTrue, returnZero, setupMoveUpEvents, Utils } from '../../Utils';
 import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager';
+import HypothesisAuthenticationManager from '../apis/HypothesisAuthenticationManager';
 import { DocServer } from '../DocServer';
 import { Docs, DocumentOptions } from '../documents/Documents';
 import { DocumentType } from '../documents/DocumentTypes';
+import { CurrentUserUtils } from '../util/CurrentUserUtils';
+import { DocumentManager } from '../util/DocumentManager';
+import GroupManager from '../util/GroupManager';
 import { HistoryUtil } from '../util/History';
-import RichTextMenu from './nodes/formattedText/RichTextMenu';
 import { Scripting } from '../util/Scripting';
+import { SelectionManager } from '../util/SelectionManager';
 import SettingsManager from '../util/SettingsManager';
-import GroupManager from '../util/GroupManager';
 import SharingManager from '../util/SharingManager';
+import { SnappingManager } from '../util/SnappingManager';
 import { Transform } from '../util/Transform';
+import { TimelineMenu } from './animationtimeline/TimelineMenu';
 import { CollectionDockingView } from './collections/CollectionDockingView';
+import FormatShapePane from "./collections/collectionFreeForm/FormatShapePane";
 import MarqueeOptionsMenu from './collections/collectionFreeForm/MarqueeOptionsMenu';
+import { PropertiesView } from './collections/collectionFreeForm/PropertiesView';
 import { CollectionLinearView } from './collections/CollectionLinearView';
+import CollectionMenu from './collections/CollectionMenu';
 import { CollectionView, CollectionViewType } from './collections/CollectionView';
 import { ContextMenu } from './ContextMenu';
 import { DictationOverlay } from './DictationOverlay';
 import { DocumentDecorations } from './DocumentDecorations';
 import GestureOverlay from './GestureOverlay';
+import { ANTIMODEMENU_HEIGHT } from './globalCssVariables.scss';
 import KeyManager from './GlobalKeyHandler';
+import { LinkMenu } from './linking/LinkMenu';
 import "./MainView.scss";
 import { MainViewNotifs } from './MainViewNotifs';
 import { AudioBox } from './nodes/AudioBox';
+import { DocumentLinksButton } from './nodes/DocumentLinksButton';
 import { DocumentView } from './nodes/DocumentView';
+import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
+import RichTextMenu from './nodes/formattedText/RichTextMenu';
+import { LinkDescriptionPopup } from './nodes/LinkDescriptionPopup';
+import { LinkDocPreview } from './nodes/LinkDocPreview';
 import { RadialMenu } from './nodes/RadialMenu';
+import { TaskCompletionBox } from './nodes/TaskCompletedBox';
 import { OverlayView } from './OverlayView';
 import PDFMenu from './pdf/PDFMenu';
 import { PreviewCursor } from './PreviewCursor';
-import { ScriptField } from '../../fields/ScriptField';
-import { TimelineMenu } from './animationtimeline/TimelineMenu';
-import { SnappingManager } from '../util/SnappingManager';
-import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
-import { DocumentManager } from '../util/DocumentManager';
-import { DocumentLinksButton } from './nodes/DocumentLinksButton';
-import { LinkMenu } from './linking/LinkMenu';
-import { LinkDocPreview } from './nodes/LinkDocPreview';
-import { TaskCompletionBox } from './nodes/TaskCompletedBox';
-import { LinkDescriptionPopup } from './nodes/LinkDescriptionPopup';
-import FormatShapePane from "./collections/collectionFreeForm/FormatShapePane";
-import HypothesisAuthenticationManager from '../apis/HypothesisAuthenticationManager';
-import CollectionMenu from './collections/CollectionMenu';
+import { undoBatch } from '../util/UndoManager';
 
 @observer
 export class MainView extends React.Component {
@@ -69,8 +72,8 @@ export class MainView extends React.Component {
 
     @observable private _panelWidth: number = 0;
     @observable private _panelHeight: number = 0;
-    @observable private _flyoutTranslate: boolean = true;
-    @observable public flyoutWidth: number = 250;
+    @observable private _flyoutTranslate: boolean = false;
+    @observable public flyoutWidth: number = 0;
     private get darkScheme() { return BoolCast(Cast(this.userDoc?.activeWorkspace, Doc, null)?.darkScheme); }
 
     @computed private get userDoc() { return Doc.UserDoc(); }
@@ -78,7 +81,27 @@ export class MainView extends React.Component {
     @computed public get mainFreeform(): Opt<Doc> { return (docs => (docs && docs.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); }
     @computed public get sidebarButtonsDoc() { return Cast(this.userDoc["tabs-buttons"], Doc) as Doc; }
 
+    @observable public sidebarContent: any = this.userDoc?.["tabs-panelContainer"];
+    @observable public panelContent: string = "none";
+    @observable public showProperties: boolean = false;
     public isPointerDown = false;
+    @computed get selectedDocumentView() {
+        if (SelectionManager.SelectedDocuments().length) {
+            return SelectionManager.SelectedDocuments()[0];
+        } else { return undefined; }
+    }
+
+    @observable _propertiesWidth: number = 0;
+    propertiesWidth = () => Math.max(0, Math.min(this._panelWidth - 50, this._propertiesWidth));
+
+    @computed get propertiesIcon() {
+        if (this.propertiesWidth() < 10) {
+            return "chevron-left";
+        } else {
+            return "chevron-right";
+        }
+    }
+    @observable propertiesDownX: number | undefined;
 
     componentDidMount() {
         DocServer.setPlaygroundFields(["dataTransition", "_viewTransition", "_panX", "_panY", "_viewScale", "_viewType", "_chromeStatus"]); // can play with these fields on someone else's
@@ -148,7 +171,10 @@ export class MainView extends React.Component {
             fa.faEye, fa.faArrowsAlt, fa.faQuoteLeft, fa.faSortAmountDown, fa.faAlignLeft, fa.faAlignCenter, fa.faAlignRight, fa.faHeading, fa.faRulerCombined,
             fa.faFillDrip, fa.faLink, fa.faUnlink, fa.faBold, fa.faItalic, fa.faChevronLeft, fa.faUnderline, fa.faStrikethrough, fa.faSuperscript, fa.faSubscript,
             fa.faIndent, fa.faEyeDropper, fa.faPaintRoller, fa.faBars, fa.faBrush, fa.faShapes, fa.faEllipsisH, fa.faHandPaper, fa.faMap, fa.faUser, faHireAHelper,
-            fa.faBezierCurve, fa.faCircle, fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, fa.faAngleUp, fa.faAngleDown, fa.faPlayCircle, fa.faClock,
+            fa.faDesktop, fa.faTrashRestore, fa.faUsers, fa.faWrench, fa.faCog, fa.faMap, fa.faBellSlash, fa.faExpandAlt, fa.faArchive, fa.faBezierCurve, fa.faCircle,
+            fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, faBuffer, fa.faExpand, fa.faUndo, fa.faSlidersH);
+        //Pres trail icons (just for the sake of merging)
+        library.add(fa.faAngleUp, fa.faAngleDown, fa.faPlayCircle, fa.faClock,
             fa.faRocket, fa.faExchangeAlt, faBuffer);
         this.initEventListeners();
         this.initAuthenticationRouters();
@@ -211,7 +237,7 @@ export class MainView extends React.Component {
         const freeformOptions: DocumentOptions = {
             x: 0,
             y: 400,
-            _width: this._panelWidth * .7,
+            _width: this._panelWidth * .7 - this.propertiesWidth(),
             _height: this._panelHeight,
             title: "Collection " + workspaceCount,
         };
@@ -277,16 +303,21 @@ export class MainView extends React.Component {
 
     @action
     onResize = (r: any) => {
-        this._panelWidth = r.offset.width;
+        this._panelWidth = r.offset.width;// - this.propertiesWidth();
         this._panelHeight = r.offset.height;
     }
-    getPWidth = () => this._panelWidth;
+
+    @action
+    getPWidth = () => this._panelWidth - this.propertiesWidth()
+
     getPHeight = () => this._panelHeight;
     getContentsHeight = () => this._panelHeight - this._buttonBarHeight;
 
-    defaultBackgroundColors = (doc: Doc) => {
+    defaultBackgroundColors = (doc: Opt<Doc>) => {
+        if (this.panelContent === doc?.title) return "lightgrey";
         if (this.darkScheme) {
             switch (doc?.type) {
+                case DocumentType.MENUICON: return "white";
                 case DocumentType.RTF || DocumentType.LABEL || DocumentType.BUTTON: return "#2d2d2d";
                 case DocumentType.LINK:
                 case DocumentType.COL: {
@@ -296,6 +327,7 @@ export class MainView extends React.Component {
             }
         } else {
             switch (doc?.type) {
+                case DocumentType.MENUICON: return "black";
                 case DocumentType.RTF: return "#f1efeb";
                 case DocumentType.BUTTON:
                 case DocumentType.LABEL: return "lightgray";
@@ -308,7 +340,8 @@ export class MainView extends React.Component {
         }
     }
     @computed get mainDocView() {
-        return <DocumentView Document={this.mainContainer!}
+        return <DocumentView
+            Document={this.mainContainer!}
             DataDoc={undefined}
             LibraryPath={emptyPath}
             addDocument={undefined}
@@ -324,7 +357,6 @@ export class MainView extends React.Component {
             NativeWidth={returnZero}
             PanelWidth={this.getPWidth}
             PanelHeight={this.getPHeight}
-            renderDepth={0}
             focus={emptyFunction}
             parentActive={returnTrue}
             whenActiveChanged={emptyFunction}
@@ -332,103 +364,63 @@ export class MainView extends React.Component {
             docFilters={returnEmptyFilter}
             ContainingCollectionView={undefined}
             ContainingCollectionDoc={undefined}
+            renderDepth={-1}
         />;
     }
     @computed get dockingContent() {
         TraceMobx();
         const mainContainer = this.mainContainer;
         const width = this.flyoutWidth;
-        return <Measure offset onResize={this.onResize}>
-            {({ measureRef }) =>
-                <div ref={measureRef} className="mainContent-div" onDrop={this.onDrop} style={{ width: `calc(100% - ${width}px)` }}>
-                    {!mainContainer ? (null) : this.mainDocView}
-                </div>
-            }
-        </Measure>;
-    }
-
-    _canClick = false;
-    onPointerDown = (e: React.PointerEvent) => {
-        if (this._flyoutTranslate) {
-            this._canClick = true;
-            this._flyoutSizeOnDown = e.clientX;
-            document.removeEventListener("pointermove", this.onPointerMove);
-            document.removeEventListener("pointerup", this.onPointerUp);
-            document.addEventListener("pointermove", this.onPointerMove);
-            document.addEventListener("pointerup", this.onPointerUp);
-            e.stopPropagation();
-            e.preventDefault();
-        }
+        return <div className="mainContent-div" onDrop={this.onDrop} style={{ width: `calc(100% - ${width}px)` }}>
+            {!mainContainer ? (null) : this.mainDocView}
+        </div>;
     }
 
     @action
-    pointerLeaveDragger = () => {
-        if (!this._flyoutTranslate) {
-            this.flyoutWidth = 0;
-            this._flyoutTranslate = true;
-        }
+    onPropertiesPointerDown = (e: React.PointerEvent) => {
+        setupMoveUpEvents(this, e, action((e: PointerEvent, down: number[], delta: number[]) => {
+            this._propertiesWidth = this._panelWidth - e.clientX;
+            return false;
+        }), returnFalse, action(() => this._propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this._panelWidth - 50, 250) : 0), false);
     }
 
     @action
-    onPointerMove = (e: PointerEvent) => {
-        this.flyoutWidth = Math.max(e.clientX, 0);
-        Math.abs(this.flyoutWidth - this._flyoutSizeOnDown) > 6 && (this._canClick = false);
-        this.sidebarButtonsDoc._columnWidth = this.flyoutWidth / 3 - 30;
-    }
-    @action
-    onPointerUp = (e: PointerEvent) => {
-        if (Math.abs(e.clientX - this._flyoutSizeOnDown) < 4 && this._canClick) {
-            this.flyoutWidth = this.flyoutWidth < 15 ? 250 : 0;
-            this.flyoutWidth && (this.sidebarButtonsDoc._columnWidth = this.flyoutWidth / 3 - 30);
+    onFlyoutPointerDown = (e: React.PointerEvent) => {
+        this.panelContent = "none";
+        if (this._flyoutTranslate) {
+            setupMoveUpEvents(this, e, action((e: PointerEvent) => {
+                this.flyoutWidth = Math.max(e.clientX, 0);
+                this.sidebarButtonsDoc._columnWidth = this.flyoutWidth / 3 - 30;
+                return false;
+            }), emptyFunction, action(() => {
+                this.flyoutWidth = this.flyoutWidth < 15 ? 250 : 0;
+                this.flyoutWidth && (this.sidebarButtonsDoc._columnWidth = this.flyoutWidth / 3 - 30);
+            }));
         }
-        document.removeEventListener("pointermove", this.onPointerMove);
-        document.removeEventListener("pointerup", this.onPointerUp);
     }
+
     flyoutWidthFunc = () => this.flyoutWidth;
     addDocTabFunc = (doc: Doc, where: string, libraryPath?: Doc[]): boolean => {
         return where === "close" ? CollectionDockingView.CloseRightSplit(doc) :
             doc.dockingConfig ? this.openWorkspace(doc) :
                 CollectionDockingView.AddRightSplit(doc, libraryPath);
     }
-    sidebarScreenToLocal = () => new Transform(0, (RichTextMenu.Instance.Pinned ? -35 : 0) + (CollectionMenu.Instance.Pinned ? -35 : 0), 1);
+    sidebarScreenToLocal = () => new Transform(0, (CollectionMenu.Instance.Pinned ? -35 : 0), 1);
+    //sidebarScreenToLocal = () => new Transform(0, (RichTextMenu.Instance.Pinned ? -35 : 0) + (CollectionMenu.Instance.Pinned ? -35 : 0), 1);
     mainContainerXf = () => this.sidebarScreenToLocal().translate(0, -this._buttonBarHeight);
 
+    @computed get closePosition() { return 55 + this.flyoutWidth; }
     @computed get flyout() {
-        const sidebarContent = this.userDoc?.["tabs-panelContainer"];
-        if (!(sidebarContent instanceof Doc)) {
-            return (null);
-        }
-        return <div className="mainView-flyoutContainer" >
-            <div className="mainView-tabButtons" style={{ height: `${this._buttonBarHeight - 10/*margin-top*/}px`, backgroundColor: StrCast(this.sidebarButtonsDoc.backgroundColor) }}>
-                <DocumentView
-                    Document={this.sidebarButtonsDoc}
-                    DataDoc={undefined}
-                    LibraryPath={emptyPath}
-                    addDocument={undefined}
-                    rootSelected={returnTrue}
-                    addDocTab={this.addDocTabFunc}
-                    pinToPres={emptyFunction}
-                    removeDocument={undefined}
-                    onClick={undefined}
-                    ScreenToLocalTransform={this.sidebarScreenToLocal}
-                    ContentScaling={returnOne}
-                    NativeHeight={returnZero}
-                    NativeWidth={returnZero}
-                    PanelWidth={this.flyoutWidthFunc}
-                    PanelHeight={this.getPHeight}
-                    renderDepth={0}
-                    focus={emptyFunction}
-                    backgroundColor={this.defaultBackgroundColors}
-                    parentActive={returnTrue}
-                    whenActiveChanged={emptyFunction}
-                    bringToFront={emptyFunction}
-                    docFilters={returnEmptyFilter}
-                    ContainingCollectionView={undefined}
-                    ContainingCollectionDoc={undefined} />
-            </div>
-            <div className="mainView-contentArea" style={{ position: "relative", height: `calc(100% - ${this._buttonBarHeight}px)`, width: "100%", overflow: "visible" }}>
+        if (!this.sidebarContent) return null;
+        return <div className="mainView-libraryFlyout">
+            <div className="mainView-contentArea" style={{ position: "relative", height: `100%`, width: "100%", overflow: "visible" }}>
+                {this.flyoutWidth > 0 ? <div className="mainView-libraryFlyout-close"
+                    onPointerDown={this.closeFlyout}>
+                    <FontAwesomeIcon icon="times" color="black" size="sm" />
+                </div> : null}
+
                 <DocumentView
-                    Document={sidebarContent}
+                    Document={this.sidebarContent}
                     DataDoc={undefined}
                     LibraryPath={emptyPath}
                     addDocument={undefined}
@@ -451,52 +443,162 @@ export class MainView extends React.Component {
                     bringToFront={emptyFunction}
                     docFilters={returnEmptyFilter}
                     ContainingCollectionView={undefined}
-                    ContainingCollectionDoc={undefined} />
-                <div className="buttonContainer" >
-                    <button className="mainView-settings" key="settings" onClick={() => SettingsManager.Instance.open()}>
-                        <FontAwesomeIcon icon="cog" size="lg" />
-                    </button>
-                </div>
+                    ContainingCollectionDoc={undefined}
+                    relative={true}
+                />
             </div>
-            {this.docButtons}
+            {this.docButtons}</div>;
+    }
+
+    @computed get menuPanel() {
+
+        return <div className="mainView-menuPanel">
+            <DocumentView
+                Document={Doc.UserDoc().menuStack as Doc}
+                DataDoc={undefined}
+                LibraryPath={emptyPath}
+                addDocument={undefined}
+                addDocTab={this.addDocTabFunc}
+                pinToPres={emptyFunction}
+                NativeHeight={returnZero}
+                NativeWidth={returnZero}
+                rootSelected={returnTrue}
+                removeDocument={returnFalse}
+                onClick={undefined}
+                ScreenToLocalTransform={this.mainContainerXf}
+                ContentScaling={returnOne}
+                PanelWidth={() => 70}
+                PanelHeight={this.getContentsHeight}
+                renderDepth={0}
+                focus={emptyFunction}
+                backgroundColor={this.defaultBackgroundColors}
+                parentActive={returnTrue}
+                whenActiveChanged={emptyFunction}
+                bringToFront={emptyFunction}
+                docFilters={returnEmptyFilter}
+                ContainingCollectionView={undefined}
+                ContainingCollectionDoc={undefined}
+                relative={true}
+                scriptContext={this}
+            />
+        </div>;
+    }
+
+
+    @action @undoBatch
+    closeFlyout = () => {
+        this.panelContent = "none";
+        this.flyoutWidth = 0;
+    }
+
+    get groupManager() { return GroupManager.Instance; }
+
+    @action @undoBatch
+    selectMenu = (str: string) => {
+        if (this.panelContent === str && this.flyoutWidth !== 0) {
+            this.panelContent = "none";
+            this.flyoutWidth = 0;
+        } else {
+            this.panelContent = str;
+            switch (this.panelContent) {
+                case "Tools": this.sidebarContent.proto = CurrentUserUtils.toolsStack; break;
+                case "Workspace": this.sidebarContent.proto = CurrentUserUtils.workspaceStack; break;
+                case "Catalog": this.sidebarContent.proto = CurrentUserUtils.catalogStack; break;
+                case "Archive": this.sidebarContent.proto = CurrentUserUtils.closedStack; break;
+                case "Settings": this.sidebarContent.proto = SettingsManager.Instance.open(); break;
+                case "Sharing": this.sidebarContent.proto = GroupManager.Instance.open(); break;
+            }
+            if (str === "Settings" || str === "Sharing" || str === "Help") {
+                this.panelContent = "none";
+                this.flyoutWidth = 0;
+            } else {
+                MainView.expandFlyout();
+            }
+        }
+        return true;
+    }
+
+    @action @undoBatch
+    closeProperties = () => {
+        this._propertiesWidth = 0;
+    }
+
+    @computed get propertiesView() {
+        TraceMobx();
+        return <div className="mainView-propertiesView" style={{
+            overflow: this.propertiesWidth() < 15 ? "hidden" : undefined
+        }}>
+            <PropertiesView
+                width={this.propertiesWidth()}
+                height={this._panelHeight}
+                renderDepth={1}
+                ScreenToLocalTransform={Transform.Identity}
+                onDown={this.closeProperties}
+            />
         </div>;
     }
 
+    @computed get mainInnerContent() {
+        const rightFlyout = this.propertiesWidth() - 1;
+        return <>
+            {this.menuPanel}
+            <div style={{ display: "contents", flexDirection: "row", position: "relative" }}>
+                <div className="mainView-flyoutContainer" style={{ width: this.flyoutWidth }}>
+                    {this.flyoutWidth !== 0 ? <div className="mainView-libraryHandle"
+                        onPointerDown={this.onFlyoutPointerDown}
+                        style={{ backgroundColor: this.defaultBackgroundColors(undefined) }}>
+                        <span title="library View Dragger" style={{
+                            width: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "100%" : "3vw",
+                            //height: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "100%" : "100vh",
+                            position: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "absolute" : "fixed",
+                            top: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "" : "0"
+                        }} />
+                        <div className="mainview-libraryHandle-icon">
+                            <FontAwesomeIcon icon="chevron-left" color="black" size="sm" /> </div>
+                    </div> : null}
+                    <div className="mainView-libraryFlyout" style={{
+                        //transformOrigin: this._flyoutTranslate ? "" : "left center",
+                        transition: this._flyoutTranslate ? "" : "width .5s",
+                        //transform: `scale(${this._flyoutTranslate ? 1 : 0.8})`,
+                        boxShadow: this._flyoutTranslate ? "" : "rgb(156, 147, 150) 0.2vw 0.2vw 0.2vw"
+                    }}>
+                        {this.flyout}
+                        {this.expandButton}
+                    </div>
+                </div>
+                {this.dockingContent}
+                {this.showProperties ? (null) :
+                    <div className="mainView-propertiesDragger" title="Properties View Dragger" onPointerDown={this.onPropertiesPointerDown}
+                        style={{ right: rightFlyout, top: "45%" }}>
+                        <div className="mainView-propertiesDragger-icon">
+                            <FontAwesomeIcon icon={this.propertiesIcon} color="white" size="sm" /> </div>
+                    </div>
+                }
+                {this.propertiesWidth() < 10 ? (null) :
+                    <div style={{ width: this.propertiesWidth() }}> {this.propertiesView} </div>}
+            </div>
+        </>;
+    }
+
     @computed get mainContent() {
-        const sidebar = this.userDoc?.["tabs-panelContainer"];
-        const n = (RichTextMenu.Instance?.Pinned ? 1 : 0) + (CollectionMenu.Instance?.Pinned ? 1 : 0);
+        //const n = (RichTextMenu.Instance?.Pinned ? 1 : 0) + (CollectionMenu.Instance?.Pinned ? 1 : 0);
+        const n = (CollectionMenu.Instance?.Pinned ? 1 : 0);
         const height = `calc(100% - ${n * Number(ANTIMODEMENU_HEIGHT.replace("px", ""))}px)`;
-        return !this.userDoc || !(sidebar instanceof Doc) ? (null) : (
-            <div className="mainView-mainContent" style={{
-                color: this.darkScheme ? "rgb(205,205,205)" : "black",
-                //change to times 2 for both pinned
-                height,
-                width: (FormatShapePane.Instance?.Pinned) ? `calc(100% - 200px)` : "100%"
-            }} >
-                <div style={{ display: "contents", flexDirection: "row", position: "relative" }}>
-                    <div className="mainView-flyoutContainer" onPointerLeave={this.pointerLeaveDragger} style={{ width: this.flyoutWidth }}>
-                        <div className="mainView-libraryHandle" onPointerDown={this.onPointerDown}
-                            style={{ backgroundColor: this.defaultBackgroundColors(sidebar) }}>
-                            <span title="library View Dragger" style={{
-                                width: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "100%" : "3vw",
-                                //height: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "100%" : "100vh",
-                                position: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "absolute" : "fixed",
-                                top: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "" : "0"
-                            }} />
-                        </div>
-                        <div className="mainView-libraryFlyout" style={{
-                            //transformOrigin: this._flyoutTranslate ? "" : "left center",
-                            transition: this._flyoutTranslate ? "" : "width .5s",
-                            //transform: `scale(${this._flyoutTranslate ? 1 : 0.8})`,
-                            boxShadow: this._flyoutTranslate ? "" : "rgb(156, 147, 150) 0.2vw 0.2vw 0.8vw"
-                        }}>
-                            {this.flyout}
-                            {this.expandButton}
-                        </div>
+        const pinned = FormatShapePane.Instance?.Pinned;
+        const innerContent = this.mainInnerContent;
+        return !this.userDoc ? (null) : (
+            <Measure offset onResize={this.onResize}>
+                {({ measureRef }) =>
+                    <div className="mainView-mainContent" ref={measureRef} style={{
+                        color: this.darkScheme ? "rgb(205,205,205)" : "black",
+                        //change to times 2 for both pinned
+                        height,
+                        width: pinned ? `calc(100% - 200px)` : "100%"
+                    }} >
+                        {innerContent}
                     </div>
-                    {this.dockingContent}
-                </div>
-            </div>);
+                }
+            </Measure>);
     }
 
     public static expandFlyout = action(() => {
@@ -506,7 +608,7 @@ export class MainView extends React.Component {
     });
 
     @computed get expandButton() {
-        return !this._flyoutTranslate ? (<div className="mainView-expandFlyoutButton" title="Re-attach sidebar" onPointerDown={MainView.expandFlyout}><FontAwesomeIcon icon="chevron-right" color="grey" size="lg" /></div>) : (null);
+        return !this._flyoutTranslate ? (<div className="mainView-expandFlyoutButton" title="Re-attach sidebar" onPointerDown={MainView.expandFlyout}></div>) : (null);
     }
 
     addButtonDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && Doc.AddDocToList(Doc.UserDoc().dockedBtns as Doc, "data", doc), true);
@@ -600,8 +702,16 @@ export class MainView extends React.Component {
         </svg>;
     }
 
+    @computed get search() {
+        return <div className="mainView-searchPanel">
+            <div style={{ float: "left", marginLeft: "10px" }}>{Doc.CurrentUserEmail}</div>
+            <div>SEARCH GOES HERE</div>
+        </div>;
+    }
+
     render() {
         return (<div className={"mainView-container" + (this.darkScheme ? "-dark" : "")} ref={this._mainViewRef}>
+
             {this.inkResources}
             <DictationOverlay />
             <SharingManager />
@@ -610,9 +720,10 @@ export class MainView extends React.Component {
             <GoogleAuthenticationManager />
             <HypothesisAuthenticationManager />
             <DocumentDecorations />
+            {/* {this.search} */}
             <CollectionMenu />
             <FormatShapePane />
-            <RichTextMenu key="rich" />
+            <div style={{ display: "none" }}><RichTextMenu key="rich" /></div>
             {LinkDescriptionPopup.descriptionPopup ? <LinkDescriptionPopup /> : null}
             {DocumentLinksButton.EditLink ? <LinkMenu location={DocumentLinksButton.EditLinkLoc} docView={DocumentLinksButton.EditLink} addDocTab={DocumentLinksButton.EditLink.props.addDocTab} changeFlyout={emptyFunction} /> : (null)}
             {LinkDocPreview.LinkInfo ? <LinkDocPreview location={LinkDocPreview.LinkInfo.Location} backgroundColor={this.defaultBackgroundColors}
diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx
index b4116e980..d7034fcfb 100644
--- a/src/client/views/PreviewCursor.tsx
+++ b/src/client/views/PreviewCursor.tsx
@@ -112,10 +112,10 @@ export class PreviewCursor extends React.Component<{}> {
                 } else if (e.clipboardData.items.length) {
                     const batch = UndoManager.StartBatch("collection view drop");
                     const files: File[] = [];
-                    for (let i = 0; i < e.clipboardData.items.length; i++) {
-                        const file = e.clipboardData.items[i].getAsFile();
+                    Array.from(e.clipboardData.items).forEach(item => {
+                        const file = item.getAsFile();
                         file && files.push(file);
-                    }
+                    });
                     const generatedDocuments = await DocUtils.uploadFilesToDocs(files, { x: newPoint[0], y: newPoint[1] });
                     generatedDocuments.forEach(PreviewCursor._addDocument);
                     batch.end();
diff --git a/src/client/views/PropertiesButtons.scss b/src/client/views/PropertiesButtons.scss
new file mode 100644
index 000000000..e099122c4
--- /dev/null
+++ b/src/client/views/PropertiesButtons.scss
@@ -0,0 +1,119 @@
+@import "globalCssVariables";
+
+$linkGap : 3px;
+
+.propertiesButtons-linkFlyout {
+    grid-column: 2/4;
+}
+
+.propertiesButtons-linkButton-empty:hover {
+    background: $main-accent;
+    transform: scale(1.05);
+    cursor: pointer;
+}
+
+.propertiesButtons-linkButton-nonempty:hover {
+    background: $main-accent;
+    transform: scale(1.05);
+    cursor: pointer;
+}
+
+.propertiesButtons-linkButton-empty,
+.propertiesButtons-linkButton-nonempty {
+    height: 30px;
+    width: 30px;
+    border-radius: 5px;
+    opacity: 0.9;
+    pointer-events: auto;
+    background-color: #121721;
+    color: #fcfbf7;
+    text-transform: uppercase;
+    letter-spacing: 2px;
+    font-size: 75%;
+    transition: transform 0.2s;
+    text-align: center;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    margin-right: 10px;
+
+    &:hover {
+        background: $main-accent;
+        transform: scale(1.05);
+        cursor: pointer;
+    }
+}
+
+.propertiesButtons {
+    margin-top: $linkGap;
+    grid-column: 1/4;
+    width: max-content;
+    height: auto;
+    display: flex;
+    flex-direction: row;
+    overflow-x: visible;
+}
+
+.onClickFlyout-editScript {
+    text-align: center;
+    border: 0.5px solid grey;
+    background-color: rgb(230, 230, 230);
+    border-radius: 9px;
+    padding: 4px;
+}
+
+
+.propertiesButtons-button {
+    pointer-events: auto;
+    padding-right: 5px;
+    width: 25px;
+    border-radius: 5px;
+    margin-right: 18px;
+}
+
+.propertiesButtons-linker {
+    height: 30px;
+    width: 30px;
+    text-align: center;
+    border-radius: 5px;
+    pointer-events: auto;
+    color: $dark-color;
+    border: $dark-color 1px solid;
+    transition: 0.2s ease all;
+    margin-right: 5px;
+}
+
+.propertiesButtons-linker:hover {
+    cursor: pointer;
+    transform: scale(1.05);
+}
+
+
+@-moz-keyframes spin {
+    100% {
+        -moz-transform: rotate(360deg);
+    }
+}
+
+@-webkit-keyframes spin {
+    100% {
+        -webkit-transform: rotate(360deg);
+    }
+}
+
+@keyframes spin {
+    100% {
+        -webkit-transform: rotate(360deg);
+        transform: rotate(360deg);
+    }
+}
+
+@keyframes shadow-pulse {
+    0% {
+        box-shadow: 0 0 0 0px rgba(0, 0, 0, 0.8);
+    }
+
+    100% {
+        box-shadow: 0 0 0 10px rgba(0, 255, 0, 0);
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
new file mode 100644
index 000000000..59e7cc7c8
--- /dev/null
+++ b/src/client/views/PropertiesButtons.tsx
@@ -0,0 +1,598 @@
+import { IconProp, library } from '@fortawesome/fontawesome-svg-core';
+import { faArrowAltCircleDown, faArrowAltCircleRight, faArrowAltCircleUp, faCheckCircle, faCloudUploadAlt, faLink, faPhotoVideo, faShare, faStopCircle, faSyncAlt, faTag, faTimes } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { action, computed, observable, runInAction } from "mobx";
+import { observer } from "mobx-react";
+import { Doc, DocListCast } from "../../fields/Doc";
+import { RichTextField } from '../../fields/RichTextField';
+import { Cast, NumCast, BoolCast } from "../../fields/Types";
+import { emptyFunction, setupMoveUpEvents, Utils } from "../../Utils";
+import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager';
+import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils';
+import { Docs, DocUtils } from '../documents/Documents';
+import { DragManager } from '../util/DragManager';
+import { CollectionDockingView, DockedFrameRenderer } from './collections/CollectionDockingView';
+import { ParentDocSelector } from './collections/ParentDocumentSelector';
+import './collections/ParentDocumentSelector.scss';
+import './PropertiesButtons.scss';
+import { MetadataEntryMenu } from './MetadataEntryMenu';
+import { DocumentView } from './nodes/DocumentView';
+import { GoogleRef } from "./nodes/formattedText/FormattedTextBox";
+import { TemplateMenu } from "./TemplateMenu";
+import { Template, Templates } from "./Templates";
+import React = require("react");
+import { Tooltip } from '@material-ui/core';
+import { SelectionManager } from '../util/SelectionManager';
+import SharingManager from '../util/SharingManager';
+import { GooglePhotos } from '../apis/google_docs/GooglePhotosClientUtils';
+import { ImageField } from '../../fields/URLField';
+import { undoBatch, UndoManager } from '../util/UndoManager';
+import { DocumentType } from '../documents/DocumentTypes';
+import { CollectionFreeFormView } from './collections/collectionFreeForm/CollectionFreeFormView';
+const higflyout = require("@hig/flyout");
+export const { anchorPoints } = higflyout;
+export const Flyout = higflyout.default;
+
+library.add(faLink);
+library.add(faTag);
+library.add(faTimes);
+library.add(faArrowAltCircleDown);
+library.add(faArrowAltCircleUp);
+library.add(faArrowAltCircleRight);
+library.add(faStopCircle);
+library.add(faCheckCircle);
+library.add(faCloudUploadAlt);
+library.add(faSyncAlt);
+library.add(faShare);
+library.add(faPhotoVideo);
+
+const cloud: IconProp = "cloud-upload-alt";
+const fetch: IconProp = "sync-alt";
+
+enum UtilityButtonState {
+    Default,
+    OpenRight,
+    OpenExternally
+}
+
+@observer
+export class PropertiesButtons extends React.Component<{}, {}> {
+    private _dragRef = React.createRef<HTMLDivElement>();
+    private _pullAnimating = false;
+    private _pushAnimating = false;
+    private _pullColorAnimating = false;
+
+    @observable private pushIcon: IconProp = "arrow-alt-circle-up";
+    @observable private pullIcon: IconProp = "arrow-alt-circle-down";
+    @observable private pullColor: string = "white";
+    @observable public isAnimatingFetch = false;
+    @observable public isAnimatingPulse = false;
+
+    @observable private openHover: UtilityButtonState = UtilityButtonState.Default;
+
+    @observable public static Instance: PropertiesButtons;
+    public static hasPushedHack = false;
+    public static hasPulledHack = false;
+
+
+    @computed get selectedDocumentView() {
+        if (SelectionManager.SelectedDocuments().length) {
+            return SelectionManager.SelectedDocuments()[0];
+        } else { return undefined; }
+    }
+    @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; }
+    @computed get dataDoc() { return this.selectedDocumentView?.dataDoc; }
+
+    @computed get onClick() { return this.selectedDoc?.onClickBehavior ? this.selectedDoc?.onClickBehavior : "nothing"; }
+
+    public startPullOutcome = action((success: boolean) => {
+        if (!this._pullAnimating) {
+            this._pullAnimating = true;
+            this.pullIcon = success ? "check-circle" : "stop-circle";
+            setTimeout(() => runInAction(() => {
+                this.pullIcon = "arrow-alt-circle-down";
+                this._pullAnimating = false;
+            }), 1000);
+        }
+    });
+
+    public startPushOutcome = action((success: boolean) => {
+        this.isAnimatingPulse = false;
+        if (!this._pushAnimating) {
+            this._pushAnimating = true;
+            this.pushIcon = success ? "check-circle" : "stop-circle";
+            setTimeout(() => runInAction(() => {
+                this.pushIcon = "arrow-alt-circle-up";
+                this._pushAnimating = false;
+            }), 1000);
+        }
+    });
+
+    public setPullState = action((unchanged: boolean) => {
+        this.isAnimatingFetch = false;
+        if (!this._pullColorAnimating) {
+            this._pullColorAnimating = true;
+            this.pullColor = unchanged ? "lawngreen" : "red";
+            setTimeout(this.clearPullColor, 1000);
+        }
+    });
+
+    private clearPullColor = action(() => {
+        this.pullColor = "white";
+        this._pullColorAnimating = false;
+    });
+
+    @computed
+    get considerGoogleDocsPush() {
+        const targetDoc = this.selectedDoc;
+        const published = targetDoc && Doc.GetProto(targetDoc)[GoogleRef] !== undefined;
+        const animation = this.isAnimatingPulse ? "shadow-pulse 1s linear infinite" : "none";
+        return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{`${published ? "Push" : "Publish"} to Google Docs`}</div></>}>
+            <div
+                className="propertiesButtons-linker"
+                style={{ animation }}
+                onClick={async () => {
+                    await GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken();
+                    !published && runInAction(() => this.isAnimatingPulse = true);
+                    PropertiesButtons.hasPushedHack = false;
+                    targetDoc[Pushes] = NumCast(targetDoc[Pushes]) + 1;
+                }}>
+                <FontAwesomeIcon className="documentdecorations-icon" icon={published ? (this.pushIcon as any) : cloud} size={published ? "sm" : "xs"} />
+            </div></Tooltip>;
+    }
+
+    @computed
+    get considerGoogleDocsPull() {
+        const targetDoc = this.selectedDoc;
+        const dataDoc = targetDoc && Doc.GetProto(targetDoc);
+        const animation = this.isAnimatingFetch ? "spin 0.5s linear infinite" : "none";
+
+        const title = (() => {
+            switch (this.openHover) {
+                default:
+                case UtilityButtonState.Default: return `${!dataDoc?.unchanged ? "Pull from" : "Fetch"} Google Docs`;
+                case UtilityButtonState.OpenRight: return "Open in Right Split";
+                case UtilityButtonState.OpenExternally: return "Open in new Browser Tab";
+            }
+        })();
+
+        return !targetDoc || !dataDoc || !dataDoc[GoogleRef] ? (null) : <Tooltip
+            title={<><div className="dash-tooltip">{title}</div></>}>
+            <div className="propertiesButtons-linker"
+                style={{ backgroundColor: this.pullColor }}
+                onPointerEnter={action(e => {
+                    if (e.altKey) {
+                        this.openHover = UtilityButtonState.OpenExternally;
+                    } else if (e.shiftKey) {
+                        this.openHover = UtilityButtonState.OpenRight;
+                    }
+                })}
+                onPointerLeave={action(() => this.openHover = UtilityButtonState.Default)}
+                onClick={async e => {
+                    const googleDocUrl = `https://docs.google.com/document/d/${dataDoc[GoogleRef]}/edit`;
+                    if (e.shiftKey) {
+                        e.preventDefault();
+                        let googleDoc = await Cast(dataDoc.googleDoc, Doc);
+                        if (!googleDoc) {
+                            const options = { _width: 600, _nativeWidth: 960, _nativeHeight: 800, isAnnotating: false, UseCors: false };
+                            googleDoc = Docs.Create.WebDocument(googleDocUrl, options);
+                            dataDoc.googleDoc = googleDoc;
+                        }
+                        CollectionDockingView.AddRightSplit(googleDoc);
+                    } else if (e.altKey) {
+                        e.preventDefault();
+                        window.open(googleDocUrl);
+                    } else {
+                        this.clearPullColor();
+                        PropertiesButtons.hasPulledHack = false;
+                        targetDoc[Pulls] = NumCast(targetDoc[Pulls]) + 1;
+                        dataDoc.unchanged && runInAction(() => this.isAnimatingFetch = true);
+                    }
+                }}>
+                <FontAwesomeIcon className="documentdecorations-icon" size="sm"
+                    style={{ WebkitAnimation: animation, MozAnimation: animation }}
+                    icon={(() => {
+                        switch (this.openHover) {
+                            default:
+                            case UtilityButtonState.Default: return dataDoc.unchanged === false ? (this.pullIcon as any) : fetch;
+                            case UtilityButtonState.OpenRight: return "arrow-alt-circle-right";
+                            case UtilityButtonState.OpenExternally: return "share";
+                        }
+                    })()}
+                />
+            </div></Tooltip>;
+    }
+    @computed
+    get pinButton() {
+        const targetDoc = this.selectedDoc;
+        const isPinned = targetDoc && Doc.isDocPinned(targetDoc);
+        return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}</div></>}>
+            <div className="propertiesButtons-linker"
+                style={{ backgroundColor: isPinned ? "white" : "rgb(37, 43, 51)", color: isPinned ? "black" : "white" }}
+                onClick={e => DockedFrameRenderer.PinDoc(targetDoc, isPinned)}>
+                <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin"
+                />
+            </div></Tooltip>;
+    }
+
+    @computed
+    get metadataButton() {
+        //const view0 = this.view0;
+        if (this.selectedDoc) {
+            return <Tooltip title={<><div className="dash-tooltip">Show metadata panel</div></>}>
+                <div className="propertiesButtons-linkFlyout">
+                    <Flyout anchorPoint={anchorPoints.LEFT_TOP}
+                        content={<MetadataEntryMenu docs={[this.selectedDoc]} suggestWithFunction />  /* tfs: @bcz This might need to be the data document? */}>
+                        <div className={"propertiesButtons-linkButton-" + "empty"} onPointerDown={e => e.stopPropagation()} >
+                            {<FontAwesomeIcon className="documentdecorations-icon" icon="tag" size="sm" />}
+                        </div>
+                    </Flyout>
+                </div></Tooltip>;
+        } else {
+            return null;
+        }
+
+    }
+
+    @observable _aliasDown = false;
+    onAliasButtonDown = (e: React.PointerEvent): void => {
+        setupMoveUpEvents(this, e, this.onAliasButtonMoved, emptyFunction, emptyFunction);
+    }
+    onAliasButtonMoved = () => {
+        if (this._dragRef.current) {
+            const dragDocView = this.selectedDocumentView!;
+            const dragData = new DragManager.DocumentDragData([dragDocView.props.Document]);
+            const [left, top] = dragDocView.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
+            dragData.dropAction = "alias";
+            DragManager.StartDocumentDrag([dragDocView.ContentDiv!], dragData, left, top, {
+                offsetX: dragData.offset[0],
+                offsetY: dragData.offset[1],
+                hideSource: false
+            });
+            return true;
+        }
+        return false;
+    }
+
+    @computed
+    get templateButton() {
+        const docView = this.selectedDocumentView;
+        const templates: Map<Template, boolean> = new Map();
+        const views = [this.selectedDocumentView];
+        Array.from(Object.values(Templates.TemplateList)).map(template =>
+            templates.set(template, views.reduce((checked, doc) => checked || doc?.props.Document["_show" + template.Name] ? true : false, false as boolean)));
+        return !docView ? (null) :
+            <Tooltip title={<><div className="dash-tooltip">Customize layout</div></>}>
+                <div className="propertiesButtons-linkFlyout">
+                    <Flyout anchorPoint={anchorPoints.LEFT_TOP} //onOpen={action(() => this._aliasDown = true)} onClose={action(() => this._aliasDown = false)}
+                        content={<TemplateMenu docViews={views.filter(v => v).map(v => v as DocumentView)} templates={templates} />}>
+                        <div className={"propertiesButtons-linkButton-empty"} >
+                            {<FontAwesomeIcon className="documentdecorations-icon" icon="edit" size="sm" />}
+                        </div>
+                    </Flyout>
+                </div></Tooltip>;
+    }
+
+    onCopy = () => {
+        if (this.selectedDoc && this.selectedDocumentView) {
+            const copy = Doc.MakeCopy(this.selectedDocumentView.props.Document, true);
+            copy.x = NumCast(this.selectedDoc.x) + NumCast(this.selectedDoc._width);
+            copy.y = NumCast(this.selectedDoc.y) + 30;
+            this.selectedDocumentView.props.addDocument?.(copy);
+        }
+    }
+
+    @computed
+    get copyButton() {
+        const targetDoc = this.selectedDoc;
+        return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Tap or Drag to create an alias"}</div></>}>
+            <div className={"propertiesButtons-linkButton-empty"}
+                ref={this._dragRef}
+                onPointerDown={this.onAliasButtonDown}
+                onClick={this.onCopy}>
+                {<FontAwesomeIcon className="documentdecorations-icon" icon="copy" size="sm" />}
+            </div>
+        </Tooltip>;
+    }
+
+    @action
+    onLock = () => {
+        this.selectedDocumentView?.toggleLockPosition();
+    }
+
+    @computed
+    get lockButton() {
+        const targetDoc = this.selectedDoc;
+        return !targetDoc ? (null) : <Tooltip
+            title={<><div className="dash-tooltip">{this.selectedDoc?.lockedPosition ?
+                "Unlock Position" : "Lock Position"}</div></>}>
+            <div className={"propertiesButtons-linkButton-empty"}
+                onPointerDown={this.onLock} >
+                {<FontAwesomeIcon className="documentdecorations-icon"
+                    icon={BoolCast(this.selectedDoc?.lockedPosition) ? "unlock" : "lock"} size="sm" />}
+            </div>
+        </Tooltip>;
+    }
+
+    @computed
+    get downloadButton() {
+        const targetDoc = this.selectedDoc;
+        return !targetDoc ? (null) : <Tooltip
+            title={<><div className="dash-tooltip">{"Download Document"}</div></>}>
+            <div className={"propertiesButtons-linkButton-empty"}
+                onPointerDown={async () => {
+                    if (this.selectedDocumentView?.props.Document) {
+                        Doc.Zip(this.selectedDocumentView?.props.Document);
+                    }
+                }}>
+                {<FontAwesomeIcon className="propertiesButtons-icon"
+                    icon="download" size="sm" />}
+            </div>
+        </Tooltip>;
+    }
+
+    @computed
+    get deleteButton() {
+        const targetDoc = this.selectedDoc;
+        return !targetDoc ? (null) : <Tooltip
+            title={<><div className="dash-tooltip">{"Delete Document"}</div></>}>
+            <div className={"propertiesButtons-linkButton-empty"}
+                onPointerDown={() => {
+                    this.selectedDocumentView?.props.ContainingCollectionView?.removeDocument(this.selectedDocumentView?.props.Document);
+                }}>
+                {<FontAwesomeIcon className="propertiesButtons-icon"
+                    icon="trash-alt" size="sm" />}
+            </div>
+        </Tooltip>;
+    }
+
+    @computed
+    get sharingButton() {
+        const targetDoc = this.selectedDoc;
+        return !targetDoc ? (null) : <Tooltip
+            title={<><div className="dash-tooltip">{"Share Document"}</div></>}>
+            <div className={"propertiesButtons-linkButton-empty"}
+                onPointerDown={() => {
+                    if (this.selectedDocumentView) {
+                        SharingManager.Instance.open(this.selectedDocumentView);
+                    }
+                }}>
+                {<FontAwesomeIcon className="propertiesButtons-icon"
+                    icon="users" size="sm" />}
+            </div>
+        </Tooltip>;
+    }
+
+    @computed
+    get onClickButton() {
+        if (this.selectedDoc) {
+            return <Tooltip title={<><div className="dash-tooltip">Choose onClick behavior</div></>}>
+                <div className="propertiesButtons-linkFlyout">
+                    <Flyout anchorPoint={anchorPoints.LEFT_TOP}
+                        content={this.onClickFlyout}>
+                        <div className={"propertiesButtons-linkButton-" + "empty"} onPointerDown={e => e.stopPropagation()} >
+                            {<FontAwesomeIcon className="documentdecorations-icon" icon="mouse-pointer" size="sm" />}
+                        </div>
+                    </Flyout>
+                </div></Tooltip>;
+        } else {
+            return null;
+        }
+    }
+
+    @action
+    handleOptionChange = (e: any) => {
+        const value = e.target.value;
+        this.selectedDoc && (this.selectedDoc.onClickBehavior = e.target.value);
+        if (value === "nothing") {
+            this.selectedDocumentView?.noOnClick();
+        } else if (value === "enterPortal") {
+            this.selectedDocumentView?.noOnClick();
+            this.selectedDocumentView?.makeIntoPortal();
+        } else if (value === "toggleDetail") {
+            this.selectedDocumentView?.noOnClick();
+            this.selectedDocumentView?.toggleDetail();
+        } else if (value === "linkInPlace") {
+            this.selectedDocumentView?.noOnClick();
+            this.selectedDocumentView?.toggleFollowLink("inPlace", true, false);
+        } else if (value === "linkOnRight") {
+            this.selectedDocumentView?.noOnClick();
+            this.selectedDocumentView?.toggleFollowLink("onRight", false, false);
+        }
+    }
+
+    @undoBatch @action
+    editOnClickScript = () => {
+        if (this.selectedDoc) {
+            DocUtils.makeCustomViewClicked(this.selectedDoc, undefined, "onClick");
+        }
+    }
+
+    @computed
+    get onClickFlyout() {
+        return <div><form>
+            <div className="radio">
+                <label>
+                    <input type="radio" value="nothing"
+                        checked={this.onClick === 'nothing'}
+                        onChange={this.handleOptionChange} />
+                    Select Document
+                </label>
+            </div>
+            <div className="radio">
+                <label>
+                    <input type="radio" value="enterPortal"
+                        checked={this.onClick === 'enterPortal'}
+                        onChange={this.handleOptionChange} />
+                    Enter Portal
+                </label>
+            </div>
+            <div className="radio">
+                <label>
+                    <input type="radio" value="toggleDetail"
+                        checked={this.onClick === 'toggleDetail'}
+                        onChange={this.handleOptionChange} />
+                    Toggle Detail
+                </label>
+            </div>
+            <div className="radio">
+                <label>
+                    <input type="radio" value="linkInPlace"
+                        checked={this.onClick === 'linkInPlace'}
+                        onChange={this.handleOptionChange} />
+                    Follow Link
+                </label>
+            </div>
+            <div className="radio">
+                <label>
+                    <input type="radio" value="linkOnRight"
+                        checked={this.onClick === 'linkOnRight'}
+                        onChange={this.handleOptionChange} />
+                    Open Link on Right
+                </label>
+            </div>
+        </form>
+            <div onPointerDown={this.editOnClickScript} className="onClickFlyout-editScript"> Edit onClick Script</div>
+        </div>;
+    }
+
+    @computed
+    get googlePhotosButton() {
+        const targetDoc = this.selectedDoc;
+        return !targetDoc ? (null) : <Tooltip
+            title={<><div className="dash-tooltip">{"Export to Google Photos"}</div></>}>
+            <div className={"propertiesButtons-linkButton-empty"}
+                onPointerDown={() => {
+                    if (this.selectedDocumentView) {
+                        GooglePhotos.Export.CollectionToAlbum({ collection: this.selectedDocumentView.Document }).then(console.log);
+                    }
+                }}>
+                {<FontAwesomeIcon className="documentdecorations-icon"
+                    icon="cloud-upload-alt" size="sm" />}
+            </div>
+        </Tooltip>;
+    }
+
+    @computed
+    get clustersButton() {
+        const targetDoc = this.selectedDoc;
+        return !targetDoc ? (null) : <Tooltip
+            title={<><div className="dash-tooltip">{this.selectedDoc?.useClusters ? "Stop Showing Clusters" : "Show Clusters"}</div></>}>
+            <div className={"propertiesButtons-linkButton-empty"}
+                style={{ backgroundColor: this.selectedDoc?.useClusters ? "#a0a0a0" : "" }}
+                onPointerDown={this.changeClusters}>
+                {<FontAwesomeIcon className="documentdecorations-icon"
+                    color={this.selectedDoc?.useClusters ? "black" : "white"}
+                    icon="braille" size="sm" />}
+            </div>
+        </Tooltip>;
+    }
+
+    @action @undoBatch
+    changeFitToBox = () => {
+        this.selectedDoc && (this.selectedDoc._fitToBox = !this.selectedDoc._fitToBox);
+    }
+
+    @action @undoBatch
+    changeClusters = () => {
+        this.selectedDoc && (this.selectedDoc.useClusters = !this.selectedDoc.useClusters);
+    }
+
+    @computed
+    get fitContentButton() {
+        const targetDoc = this.selectedDoc;
+        return !targetDoc ? (null) : <Tooltip
+            title={<><div className="dash-tooltip">{this.selectedDoc?._fitToBox ? "Stop Fitting Content" : "Fit Content"}</div></>}>
+            <div className={"propertiesButtons-linkButton-empty"}
+                style={{ backgroundColor: this.selectedDoc?._fitToBox ? "#a0a0a0" : "" }}
+                onPointerDown={this.changeFitToBox}>
+                {<FontAwesomeIcon className="documentdecorations-icon"
+                    color={this.selectedDoc?._fitToBox ? "black" : "white"}
+                    icon="expand" size="sm" />}
+            </div>
+        </Tooltip>;
+    }
+
+    // @computed
+    // get importButton() {
+    //     const targetDoc = this.selectedDoc;
+    //     return !targetDoc ? (null) : <Tooltip
+    //         title={<><div className="dash-tooltip">{"Import a Document"}</div></>}>
+    //         <div className={"propertiesButtons-linkButton-empty"}
+    //             onPointerDown={() => {
+    //                 if (this.selectedDocumentView) {
+    //                     CollectionFreeFormView.importDocument(100, 100);
+    //                 }
+    //             }}>
+    //             {<FontAwesomeIcon className="documentdecorations-icon"
+    //                 icon="upload" size="sm" />}
+    //         </div>
+    //     </Tooltip>;
+    // }
+
+
+    render() {
+        if (!this.selectedDoc) return (null);
+
+        const isText = this.selectedDoc[Doc.LayoutFieldKey(this.selectedDoc)] instanceof RichTextField;
+        const considerPull = isText && this.considerGoogleDocsPull;
+        const considerPush = isText && this.considerGoogleDocsPush;
+        const isImage = this.selectedDoc[Doc.LayoutFieldKey(this.selectedDoc)] instanceof ImageField;
+        const isCollection = this.selectedDoc.type === DocumentType.COL ? true : false;
+        const isFreeForm = this.selectedDoc._viewType === "freeform" ? true : false;
+
+        return <div><div className="propertiesButtons" style={{ paddingBottom: "5.5px" }}>
+            <div className="propertiesButtons-button">
+                {this.templateButton}
+            </div>
+            {/* <div className="propertiesButtons-button">
+                {this.metadataButton}
+            </div> */}
+            <div className="propertiesButtons-button">
+                {this.pinButton}
+            </div>
+            <div className="propertiesButtons-button">
+                {this.copyButton}
+            </div>
+            <div className="propertiesButtons-button">
+                {this.lockButton}
+            </div>
+            <div className="propertiesButtons-button">
+                {this.downloadButton}
+            </div>
+        </div>
+            <div className="propertiesButtons">
+                <div className="propertiesButtons-button">
+                    {this.deleteButton}
+                </div>
+                <div className="propertiesButtons-button">
+                    {this.onClickButton}
+                </div>
+                <div className="propertiesButtons-button">
+                    {this.sharingButton}
+                </div>
+                <div className="propertiesButtons-button" style={{ display: !considerPush ? "none" : "" }}>
+                    {this.considerGoogleDocsPush}
+                </div>
+                <div className="propertiesButtons-button" style={{ display: !considerPull ? "none" : "" }}>
+                    {this.considerGoogleDocsPull}
+                </div>
+                <div className="propertiesButtons-button" style={{ display: !isImage ? "none" : "" }}>
+                    {this.googlePhotosButton}
+                </div>
+                {/* <div className="propertiesButtons-button" style={{ display: !isCollection ? "none" : "" }}>
+                    {this.importButton}
+                </div> */}
+
+                <div className="propertiesButtons-button" style={{ display: !isFreeForm ? "none" : "" }}>
+                    {this.clustersButton}
+                </div>
+
+                <div className="propertiesButtons-button" style={{ display: !isFreeForm ? "none" : "" }}>
+                    {this.fitContentButton}
+                </div>
+
+            </div>
+        </div>;
+    }
+}
diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss
index 9b14df760..6d93b2ba8 100644
--- a/src/client/views/collections/CollectionDockingView.scss
+++ b/src/client/views/collections/CollectionDockingView.scss
@@ -12,6 +12,7 @@
         width: 100%;
         height: 100%;
         position: absolute;
+
         .miniThumb {
             background: #25252525;
             position: absolute;
@@ -89,6 +90,7 @@
     transform: translate(0px, -3px);
     cursor: grab;
 }
+
 .lm_title.focus-visible {
     cursor: text;
 }
@@ -96,23 +98,25 @@
 .lm_title_wrap {
     overflow: hidden;
     height: 19px;
-    margin-top: -3px;
-    display:inline-block;
+    margin-top: -2px;
+    display: inline-block;
 }
+
 .lm_active .lm_title {
     border: solid 1px lightgray;
 }
+
 .lm_header .lm_tab .lm_close_tab {
     position: absolute;
     text-align: center;
 }
 
 .lm_header .lm_tab {
-    padding-right : 20px;
+    padding-right: 20px;
 }
 
 .lm_popout {
-    display:none;
+    display: none;
 }
 
 .messageCounter {
@@ -135,6 +139,7 @@
     position: absolute;
     top: 0;
     left: 0;
+
     // overflow: hidden;  // bcz: menus don't show up when this is on (e.g., the parentSelectorMenu)
     .collectionDockingView-gear {
         padding-left: 5px;
@@ -142,7 +147,10 @@
         width: 18px;
         display: inline-block;
         margin: auto;
+
+        display: none;
     }
+
     .collectionDockingView-dragAsDocument {
         touch-action: none;
         position: absolute;
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index f658e9816..d685fac4e 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -1,9 +1,8 @@
 import 'golden-layout/src/css/goldenlayout-base.css';
 import 'golden-layout/src/css/goldenlayout-dark-theme.css';
-import { action, computed, Lambda, observable, reaction, runInAction, trace } from "mobx";
+import { action, computed, Lambda, observable, reaction, runInAction, trace, IReactionDisposer } from "mobx";
 import { observer } from "mobx-react";
 import * as ReactDOM from 'react-dom';
-import Measure from "react-measure";
 import * as GoldenLayout from "../../../client/goldenLayout";
 import { DateField } from '../../../fields/DateField';
 import { Doc, DocListCast, Field, Opt, DataSym } from "../../../fields/Doc";
@@ -507,7 +506,6 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
 
             const doc = await DocServer.GetRefField(tab.contentItem.config.props.documentId) as Doc;
             if (doc instanceof Doc) {
-                //tab.titleElement[0].outerHTML = `<input class='lm_title' style="background:black" value='${doc.title}' />`;
                 tab.titleElement[0].onclick = (e: any) => tab.titleElement[0].focus();
                 tab.titleElement[0].onchange = (e: any) => {
                     tab.titleElement[0].size = e.currentTarget.value.length + 1;
@@ -522,6 +520,10 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                 gearSpan.style.paddingLeft = "0px";
                 gearSpan.style.paddingRight = "12px";
                 const stack = tab.contentItem.parent;
+                tab.element[0].onpointerdown = (e: any) => {
+                    const view = DocumentManager.Instance.getDocumentView(doc);
+                    view && SelectionManager.SelectDoc(view, false);
+                };
                 // shifts the focus to this tab when another tab is dragged over it
                 tab.element[0].onmouseenter = (e: any) => {
                     if (!this._isPointerDown || !SnappingManager.GetIsDragging()) return;
@@ -676,10 +678,15 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
     @observable private _panelHeight = 0;
     @observable private _document: Opt<Doc>;
     @observable private _isActive: boolean = false;
+    _tabReaction: IReactionDisposer | undefined;
 
     get _stack(): any {
         return (this.props as any).glContainer.parent.parent;
     }
+    get _tab(): any {
+        const tab = (this.props as any).glContainer.tab.element[0] as HTMLElement;
+        return tab.getElementsByClassName("lm_title")?.[0];
+    }
     constructor(props: any) {
         super(props);
         DocServer.GetRefField(this.props.documentId).then(action((f: Opt<Field>) => this._document = f as Doc));
@@ -740,9 +747,16 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
         this.props.glContainer.layoutManager.on("activeContentItemChanged", this.onActiveContentItemChanged);
         this.props.glContainer.on("tab", this.onActiveContentItemChanged);
         this.onActiveContentItemChanged();
+        this._tabReaction = reaction(() => ({ views: SelectionManager.SelectedDocuments(), color: StrCast(this._document?._backgroundColor, "white") }),
+            (data) => {
+                const selected = data.views.some(v => Doc.AreProtosEqual(v.props.Document, this._document));
+                this._tab.style.backgroundColor = selected ? data.color : "";
+            }
+        );
     }
 
     componentWillUnmount() {
+        this._tabReaction?.();
         this.props.glContainer.layoutManager.off("activeContentItemChanged", this.onActiveContentItemChanged);
         this.props.glContainer.off("tab", this.onActiveContentItemChanged);
     }
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 0ca86172f..fdd1b4e81 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -25,6 +25,8 @@ import { SelectionManager } from "../../util/SelectionManager";
 import { DocumentView } from "../nodes/DocumentView";
 import { ColorState } from "react-color";
 import { ObjectField } from "../../../fields/ObjectField";
+import RichTextMenu from "../nodes/formattedText/RichTextMenu";
+import { RichTextField } from "../../../fields/RichTextField";
 import { ScriptField } from "../../../fields/ScriptField";
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { DocUtils } from "../../documents/Documents";
@@ -47,7 +49,7 @@ export default class CollectionMenu extends AntimodeMenu {
 
     componentDidMount() {
         reaction(() => SelectionManager.SelectedDocuments().length && SelectionManager.SelectedDocuments()[0],
-            (doc) => doc && this.SetSelection(doc))
+            (doc) => doc && this.SetSelection(doc));
     }
 
     @action
@@ -160,7 +162,8 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
         initialize: (button: Doc) => { button['target-docFilters'] = this.target._docFilters instanceof ObjectField ? ObjectField.MakeCopy(this.target._docFilters as any as ObjectField) : ""; },
     };
 
-    _freeform_commands = [this._viewCommand, this._saveFilterCommand, this._fitContentCommand, this._clusterCommand, this._contentCommand, this._templateCommand, this._narrativeCommand];
+    @computed get _freeform_commands() { return Doc.UserDoc().noviceMode ? [this._viewCommand, this._saveFilterCommand] : [this._viewCommand, this._saveFilterCommand, this._contentCommand, this._templateCommand, this._narrativeCommand]; }
+
     _stacking_commands = [this._contentCommand, this._templateCommand];
     _masonry_commands = [this._contentCommand, this._templateCommand];
     _schema_commands = [this._templateCommand, this._narrativeCommand];
@@ -308,18 +311,32 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
         </div>;
     }
 
+    @computed get selectedDocumentView() {
+        if (SelectionManager.SelectedDocuments().length) {
+            return SelectionManager.SelectedDocuments()[0];
+        } else { return undefined; }
+    }
+    @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; }
+    @computed get isText() {
+        if (this.selectedDoc) {
+            return this.selectedDoc[Doc.LayoutFieldKey(this.selectedDoc)] instanceof RichTextField;
+        }
+        else return false;
+    }
+
     render() {
         return (
             <div className="collectionMenu-cont" >
                 <div className="collectionMenu">
                     <div className="collectionViewBaseChrome">
-                        {this.props.type === CollectionViewType.Invalid || this.props.type === CollectionViewType.Docking ? (null) : this.viewModes}
-                        {this.props.type === CollectionViewType.Docking ? (null) : this.templateChrome}
-                        <div className="collectionViewBaseChrome-viewSpecs" title="filter documents to show" style={{ display: "grid" }}>
+                        {this.props.type === CollectionViewType.Invalid ||
+                            this.props.type === CollectionViewType.Docking || this.isText ? (null) : this.viewModes}
+                        {this.props.type === CollectionViewType.Docking || this.isText ? (null) : this.templateChrome}
+                        {/* <div className="collectionViewBaseChrome-viewSpecs" title="filter documents to show" style={{ display: "grid" }}>
                             <button className={"antimodeMenu-button"} onClick={this.toggleViewSpecs} >
                                 <FontAwesomeIcon icon="filter" size="lg" />
                             </button>
-                        </div>
+                        </div> */}
 
                         {this.props.docView.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Freeform ? (null) : <button className={"antimodeMenu-button"} key="float"
                             style={{ backgroundColor: !this.props.docView.layoutDoc.isAnnotating ? "121212" : undefined, borderRight: "1px solid gray" }}
@@ -356,6 +373,20 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
     @computed get childDocs() {
         return DocListCast(this.dataField);
     }
+
+    @computed get selectedDocumentView() {
+        if (SelectionManager.SelectedDocuments().length) {
+            return SelectionManager.SelectedDocuments()[0];
+        } else { return undefined; }
+    }
+    @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; }
+    @computed get isText() {
+        if (this.selectedDoc) {
+            return this.selectedDoc[Doc.LayoutFieldKey(this.selectedDoc)] instanceof RichTextField;
+        }
+        else return false;
+    }
+
     @undoBatch
     @action
     nextKeyframe = (): void => {
@@ -384,6 +415,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
     miniMap = (): void => {
         this.document.hideMinimap = !this.document.hideMinimap;
     }
+
     private _palette = ["#D0021B", "#F5A623", "#F8E71C", "#8B572A", "#7ED321", "#417505", "#9013FE", "#4A90E2", "#50E3C2", "#B8E986", "#000000", "#4A4A4A", "#9B9B9B", "#FFFFFF", ""];
     private _width = ["1", "5", "10", "100"];
     // private _draw = ["⎯", "→", "↔︎", "∿", "↝", "↭", "ロ", "O", "∆"];
@@ -523,40 +555,44 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
     }
 
     @computed get formatPane() {
-        return <button className="antimodeMenu-button" key="format" title="toggle foramatting pane"
-            onPointerDown={action(e => FormatShapePane.Instance.Pinned = !FormatShapePane.Instance.Pinned)}
-            style={{ backgroundColor: this._fillBtn ? "121212" : "" }}>
-            <FontAwesomeIcon icon="angle-double-right" size="lg" />
-        </button>;
+        // return <button className="antimodeMenu-button" key="format" title="toggle foramatting pane"
+        //     onPointerDown={action(e => FormatShapePane.Instance.Pinned = !FormatShapePane.Instance.Pinned)}
+        //     style={{ backgroundColor: this._fillBtn ? "121212" : "" }}>
+        //     <FontAwesomeIcon icon="angle-double-right" size="lg" />
+        // </button>;
+        return null;
     }
 
     render() {
         return !this.props.docView.layoutDoc ? (null) : <div className="collectionFreeFormMenu-cont">
-            {this.props.docView.props.renderDepth !== 0 ? (null) :
+            {this.props.docView.props.renderDepth !== 0 || this.isText ? (null) :
                 <div key="map" title="mini map" className="backKeyframe" onClick={this.miniMap}>
                     <FontAwesomeIcon icon={"map"} size={"lg"} />
                 </div>
             }
-            <div key="back" title="back frame" className="backKeyframe" onClick={this.prevKeyframe}>
+            {!!!this.isText ? <div key="back" title="back frame" className="backKeyframe" onClick={this.prevKeyframe}>
                 <FontAwesomeIcon icon={"caret-left"} size={"lg"} />
-            </div>
-            <div key="num" title="toggle view all" className="numKeyframe" style={{ backgroundColor: this.document.editing ? "#759c75" : "#c56565" }}
+            </div> : null}
+            {!!!this.isText ? <div key="num" title="toggle view all" className="numKeyframe" style={{ backgroundColor: this.document.editing ? "#759c75" : "#c56565" }}
                 onClick={action(() => this.document.editing = !this.document.editing)} >
                 {NumCast(this.document.currentFrame)}
-            </div>
-            <div key="fwd" title="forward frame" className="fwdKeyframe" onClick={this.nextKeyframe}>
+            </div> : null}
+            {!!!this.isText ? <div key="fwd" title="forward frame" className="fwdKeyframe" onClick={this.nextKeyframe}>
                 <FontAwesomeIcon icon={"caret-right"} size={"lg"} />
-            </div>
+            </div> : null}
 
-            {!this.props.isOverlay || this.document.type !== DocumentType.WEB ? (null) :
+            {!this.props.isOverlay || this.document.type !== DocumentType.WEB || this.isText ? (null) :
                 <button className={"antimodeMenu-button"} key="hypothesis"
-                    style={{ backgroundColor: !this.props.docView.layoutDoc.isAnnotating ? "121212" : undefined, borderRight: "1px solid gray" }}
+                    style={{
+                        backgroundColor: !this.props.docView.layoutDoc.isAnnotating ? "121212" : undefined,
+                        borderRight: "1px solid gray"
+                    }}
                     title="Use Hypothesis"
                     onClick={() => this.props.docView.layoutDoc.isAnnotating = !this.props.docView.layoutDoc.isAnnotating}>
                     <FontAwesomeIcon icon={["fab", "hire-a-helper"]} size={"lg"} />
                 </button>
             }
-            {!this.props.isOverlay || this.props.docView.layoutDoc.isAnnotating ?
+            {(!this.props.isOverlay || this.props.docView.layoutDoc.isAnnotating) && !this.isText ?
                 <>
                     {this.drawButtons}
                     {this.widthPicker}
@@ -566,6 +602,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
                 </> :
                 (null)
             }
+            {this.isText ? <RichTextMenu key="rich" /> : null}
         </div>;
     }
 }
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 5553bbbb7..f67e049fd 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -253,7 +253,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             <div className="collectionSchema-headerMenu-group">
                 <div onClick={() => this.typesDropdownChange(!this._openTypes)}>
                     <label>Column type:</label>
-                    <FontAwesomeIcon icon={"caret-down"} size="sm" style={{ float: "right" }} />
+                    <FontAwesomeIcon icon={"caret-down"} size="lg" style={{ float: "right" }} />
                 </div>
                 {this._openTypes ? allColumnTypes : justColType}
             </div >
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 425dc90e4..a104ac011 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -227,6 +227,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument)
             addDocTab={this.addDocTab}
             bringToFront={returnFalse}
             ContentScaling={returnOne}
+            scriptContext={this.props.scriptContext}
             pinToPres={this.props.pinToPres}
         />;
     }
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 26d2ee8a3..68c233a16 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -351,7 +351,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
             {this.props.parent.Document._columnsHideIfEmpty ? (null) : headingView}
             {
                 this.collapsed ? (null) :
-                    <div style={{ marginTop: 5 }}>
+                    <div>
                         <div key={`${heading}-stack`} className={`collectionStackingView-masonry${singleColumn ? "Single" : "Grid"}`}
                             style={{
                                 padding: singleColumn ? `${columnYMargin}px ${0}px ${style.yMargin}px ${0}px` : `${columnYMargin}px ${0}px`,
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 9f78c15eb..c90e85271 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -296,7 +296,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
                             const reg = new RegExp(Utils.prepend(""), "g");
                             const modHtml = srcUrl ? html.replace(reg, srcUrl) : html;
                             const htmlDoc = Docs.Create.HtmlDocument(modHtml, { ...options, title: "-web page-", _width: 300, _height: 300 });
-                            Doc.GetProto(htmlDoc)["data-text"] = Doc.GetProto(htmlDoc)["text"] = text;
+                            Doc.GetProto(htmlDoc)["data-text"] = Doc.GetProto(htmlDoc).text = text;
                             this.props.addDocument(htmlDoc);
                             if (srcWeb) {
                                 const focusNode = (SelectionManager.SelectedDocuments()[0].ContentDiv?.getElementsByTagName("iframe")[0].contentDocument?.getSelection()?.focusNode as any);
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index b8996c178..e5c4b9187 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -90,7 +90,10 @@ class TreeView extends React.Component<TreeViewProps> {
     get displayName() { return "TreeView(" + this.doc.title + ")"; }  // this makes mobx trace() statements more descriptive
     get defaultExpandedView() { return this.childDocs ? this.fieldKey : StrCast(this.doc.defaultExpandedView, this.noviceMode ? "layout" : "fields"); }
     @observable _overrideTreeViewOpen = false; // override of the treeViewOpen field allowing the display state to be independent of the document's state
-    set treeViewOpen(c: boolean) { if (this.props.treeViewPreventOpen) this._overrideTreeViewOpen = c; else this.doc.treeViewOpen = this._overrideTreeViewOpen = c; }
+    set treeViewOpen(c: boolean) {
+        if (this.props.treeViewPreventOpen) this._overrideTreeViewOpen = c;
+        else this.doc.treeViewOpen = this._overrideTreeViewOpen = c;
+    }
     @computed get treeViewOpen() { return (!this.props.treeViewPreventOpen && !this.doc.treeViewPreventOpen && BoolCast(this.doc.treeViewOpen)) || this._overrideTreeViewOpen; }
     @computed get treeViewExpandedView() { return StrCast(this.doc.treeViewExpandedView, this.defaultExpandedView); }
     @computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.containingCollection.maxEmbedHeight, 200); }
@@ -101,7 +104,7 @@ class TreeView extends React.Component<TreeViewProps> {
         const layout = Doc.LayoutField(this.doc) instanceof Doc ? Doc.LayoutField(this.doc) as Doc : undefined;
         return ((this.props.dataDoc ? DocListCast(this.props.dataDoc[field]) : undefined) || // if there's a data doc for an expanded template, use it's data field
             (layout ? DocListCast(layout[field]) : undefined) || // else if there's a layout doc, display it's fields
-            DocListCast(this.doc[field])) as Doc[]; // otherwise use the document's data field
+            DocListCast(this.doc[field])); // otherwise use the document's data field
     }
     @computed get childDocs() { return this.childDocList(this.fieldKey); }
     @computed get childLinks() { return this.childDocList("links"); }
diff --git a/src/client/views/collections/CollectionView.scss b/src/client/views/collections/CollectionView.scss
index b630f9cf8..a5aef86de 100644
--- a/src/client/views/collections/CollectionView.scss
+++ b/src/client/views/collections/CollectionView.scss
@@ -24,6 +24,7 @@
         border-right: unset;
         z-index: 2;
     }
+
     .collectionTimeView-treeView {
         display: flex;
         flex-direction: column;
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 7e7ea6786..62e8dc26a 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -78,6 +78,7 @@ export interface CollectionViewCustomProps {
     childLayoutTemplate?: () => Opt<Doc>;  // specify a layout Doc template to use for children of the collection
     childLayoutString?: string;  // specify a layout string to use for children of the collection
     childOpacity?: () => number;
+    hideFilter?: true;
 }
 
 export interface CollectionRenderProps {
@@ -309,7 +310,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
 
             const options = cm.findByDescription("Options...");
             const optionItems = options && "subitems" in options ? options.subitems : [];
-            optionItems.splice(0, 0, { description: `${this.props.Document.forceActive ? "Select" : "Force"} Contents Active`, event: () => this.props.Document.forceActive = !this.props.Document.forceActive, icon: "project-diagram" });
+            !Doc.UserDoc().noviceMode ? optionItems.splice(0, 0, { description: `${this.props.Document.forceActive ? "Select" : "Force"} Contents Active`, event: () => this.props.Document.forceActive = !this.props.Document.forceActive, icon: "project-diagram" }) : null;
             if (this.props.Document.childLayout instanceof Doc) {
                 optionItems.push({ description: "View Child Layout", event: () => this.props.addDocTab(this.props.Document.childLayout as Doc, "onRight"), icon: "project-diagram" });
             }
@@ -368,7 +369,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
     get _facetWidth() { return NumCast(this.props.Document._facetWidth); }
     set _facetWidth(value) { this.props.Document._facetWidth = value; }
 
-    bodyPanelWidth = () => this.props.PanelWidth() - this.facetWidth();
+    bodyPanelWidth = () => this.props.PanelWidth();
     facetWidth = () => Math.max(0, Math.min(this.props.PanelWidth() - 25, this._facetWidth));
 
     @computed get dataDoc() {
@@ -490,6 +491,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
             return false;
         }), returnFalse, action(() => this._facetWidth = this.facetWidth() < 15 ? Math.min(this.props.PanelWidth() - 25, 200) : 0), false);
     }
+
     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() {
@@ -559,6 +561,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
                 </div>
             </div>;
     }
+
     childLayoutTemplate = () => this.props.childLayoutTemplate?.() || Cast(this.props.Document.childLayoutTemplate, Doc, null);
     childLayoutString = this.props.childLayoutString || StrCast(this.props.Document.childLayoutString);
 
@@ -588,11 +591,11 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
                         Utils.CorsProxy(Cast(d.data, ImageField)!.url.href) : Cast(d.data, ImageField)!.url.href
                     :
                     ""))}
-            {(!this.props.isSelected() && !this.props.Document.forceActive) || this.props.Document.hideFilterView ? (null) :
+            {/* {(!this.props.isSelected() && !this.props.Document.forceActive) || this.props.Document.hideFilterView ? (null) :
                 <div className="collectionView-filterDragger" title="library View Dragger" onPointerDown={this.onPointerDown}
                     style={{ right: this.facetWidth() - 1, top: this.props.Document._viewType === CollectionViewType.Docking ? "25%" : "55%" }} />
             }
-            {this.facetWidth() < 10 ? (null) : this.filterView}
+            {this.facetWidth() < 10 ? (null) : this.filterView}  */}
         </div>);
     }
 }
diff --git a/src/client/views/collections/ParentDocumentSelector.tsx b/src/client/views/collections/ParentDocumentSelector.tsx
index 8c0b8de9d..532dd6abc 100644
--- a/src/client/views/collections/ParentDocumentSelector.tsx
+++ b/src/client/views/collections/ParentDocumentSelector.tsx
@@ -42,14 +42,14 @@ export class SelectorContextMenu extends React.Component<SelectorProps> {
     async fetchDocuments() {
         const aliases = (await SearchUtil.GetAliasesOfDocument(this.props.Document));
         const containerProtoSets = await Promise.all(aliases.map(async alias =>
-            await Promise.all((await SearchUtil.Search("", true, { fq: `data_l:"${alias[Id]}"` })).docs)));
+            ((await SearchUtil.Search("", true, { fq: `data_l:"${alias[Id]}"` })).docs)));
         const containerProtos = containerProtoSets.reduce((p, set) => { set.map(s => p.add(s)); return p; }, new Set<Doc>());
         const containerSets = await Promise.all(Array.from(containerProtos.keys()).map(async container => {
-            return (await SearchUtil.GetAliasesOfDocument(container));
+            return (SearchUtil.GetAliasesOfDocument(container));
         }));
         const containers = containerSets.reduce((p, set) => { set.map(s => p.add(s)); return p; }, new Set<Doc>());
         const doclayoutSets = await Promise.all(Array.from(containers.keys()).map(async (dp) => {
-            return (await SearchUtil.GetAliasesOfDocument(dp));
+            return (SearchUtil.GetAliasesOfDocument(dp));
         }));
         const doclayouts = Array.from(doclayoutSets.reduce((p, set) => { set.map(s => p.add(s)); return p; }, new Set<Doc>()).keys());
         runInAction(() => {
diff --git a/src/client/views/collections/SchemaTable.tsx b/src/client/views/collections/SchemaTable.tsx
index cde795098..7e2840c2c 100644
--- a/src/client/views/collections/SchemaTable.tsx
+++ b/src/client/views/collections/SchemaTable.tsx
@@ -148,7 +148,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     @action
-    changeTitleMode = () => this._showTitleDropdown = !this._showTitleDropdown;
+    changeTitleMode = () => this._showTitleDropdown = !this._showTitleDropdown
 
     @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
     @computed get tableColumns(): Column<Doc>[] {
@@ -208,7 +208,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
                 }}>
                 {col.heading}</div>;
 
-            const sortIcon = col.desc === undefined ? "circle" : col.desc === true ? "caret-down" : "caret-up";
+            const sortIcon = col.desc === undefined ? "caret-right" : col.desc === true ? "caret-down" : "caret-up";
 
             const header =
                 <div //className="collectionSchemaView-header"
@@ -224,12 +224,12 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
                         {keysDropdown}
                     </div>
                     <div onClick={e => this.changeSorting(col)}
-                        style={{ paddingRight: "6px", display: "inline" }}>
+                        style={{ paddingRight: "6px", marginLeft: "4px", display: "inline" }}>
                         <FontAwesomeIcon icon={sortIcon} size="sm" />
                     </div>
                     <div onClick={e => this.props.openHeader(col, e.clientX, e.clientY)}
                         style={{ float: "right", paddingRight: "6px" }}>
-                        <FontAwesomeIcon icon={"compass"} size="sm" />
+                        <FontAwesomeIcon icon={"cog"} size="sm" />
                     </div>
                 </div>;
 
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 151acb64d..109808956 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1145,7 +1145,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
     @action
     componentDidMount() {
         super.componentDidMount?.();
-        this._layoutComputeReaction = reaction(() => { TraceMobx(); return this.doLayoutComputation },
+        this._layoutComputeReaction = reaction(() => this.doLayoutComputation,
             (elements) => this._layoutElements = elements || [],
             { fireImmediately: true, name: "doLayout" });
 
@@ -1240,13 +1240,15 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         const appearanceItems = appearance && "subitems" in appearance ? appearance.subitems : [];
         appearanceItems.push({ description: "Reset View", event: () => { this.props.Document._panX = this.props.Document._panY = 0; this.props.Document[this.scaleFieldKey] = 1; }, icon: "compress-arrows-alt" });
         appearanceItems.push({ description: `${this.fitToContent ? "Make Zoomable" : "Scale to Window"}`, event: () => this.Document._fitToBox = !this.fitToContent, icon: !this.fitToContent ? "expand-arrows-alt" : "compress-arrows-alt" });
-        appearanceItems.push({ description: "Arrange contents in grid", event: this.layoutDocsInGrid, icon: "table" });
+        !Doc.UserDoc().noviceMode ? appearanceItems.push({ description: "Arrange contents in grid", event: this.layoutDocsInGrid, icon: "table" }) : null;
         !appearance && ContextMenu.Instance.addItem({ description: "Appearance...", subitems: appearanceItems, icon: "eye" });
 
         const viewctrls = ContextMenu.Instance.findByDescription("UI Controls...");
         const viewCtrlItems = viewctrls && "subitems" in viewctrls ? viewctrls.subitems : [];
-        viewCtrlItems.push({ description: (Doc.UserDoc().showSnapLines ? "Hide" : "Show") + " Snap Lines", event: () => Doc.UserDoc().showSnapLines = !Doc.UserDoc().showSnapLines, icon: "compress-arrows-alt" });
-        viewCtrlItems.push({ description: (this.Document.useClusters ? "Hide" : "Show") + " Clusters", event: () => this.updateClusters(!this.Document.useClusters), icon: "braille" });
+
+
+        !Doc.UserDoc().noviceMode ? viewCtrlItems.push({ description: (Doc.UserDoc().showSnapLines ? "Hide" : "Show") + " Snap Lines", event: () => Doc.UserDoc().showSnapLines = !Doc.UserDoc().showSnapLines, icon: "compress-arrows-alt" }) : null;
+        !Doc.UserDoc().noviceMode ? viewCtrlItems.push({ description: (this.Document.useClusters ? "Hide" : "Show") + " Clusters", event: () => this.updateClusters(!this.Document.useClusters), icon: "braille" }) : null;
         !viewctrls && ContextMenu.Instance.addItem({ description: "UI Controls...", subitems: viewCtrlItems, icon: "eye" });
 
         const options = ContextMenu.Instance.findByDescription("Options...");
@@ -1291,7 +1293,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
                         setTimeout(() => {
                             SearchUtil.Search(`{!join from=id to=proto_i}id:link*`, true, {}).then(docs => {
                                 docs.docs.forEach(d => LinkManager.Instance.addLink(d));
-                            })
+                            });
                         }, 2000); // need to give solr some time to update so that this query will find any link docs we've added.
                     }
                 }
diff --git a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
index ddc282e57..6263be261 100644
--- a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
+++ b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
@@ -13,7 +13,6 @@ import AntimodeMenu from "../../AntimodeMenu";
 import "./FormatShapePane.scss";
 import { undoBatch } from "../../../util/UndoManager";
 import { ColorState, SketchPicker } from 'react-color';
-import { DocumentView } from "../../../views/nodes/DocumentView"
 
 @observer
 export default class FormatShapePane extends AntimodeMenu {
@@ -124,12 +123,12 @@ export default class FormatShapePane extends AntimodeMenu {
                     console.log(ink);
                     if (ink) {
                         const newPoints: { X: number, Y: number }[] = [];
-                        for (var j = 0; j < ink.length; j++) {
+                        ink.forEach(i => {
                             // (new x — oldx) + (oldxpoint * newWidt)/oldWidth 
-                            const newX = (doc.x - oldX) + (ink[j].X * doc._width) / oldWidth;
-                            const newY = (doc.y - oldY) + (ink[j].Y * doc._height) / oldHeight;
+                            const newX = ((doc.x || 0) - oldX) + (i.X * (doc._width || 0)) / oldWidth;
+                            const newY = ((doc.y || 0) - oldY) + (i.Y * (doc._height || 0)) / oldHeight;
                             newPoints.push({ X: newX, Y: newY });
-                        }
+                        });
                         doc.data = new InkField(newPoints);
                     }
                 }
@@ -148,12 +147,12 @@ export default class FormatShapePane extends AntimodeMenu {
                     console.log(ink);
                     if (ink) {
                         const newPoints: { X: number, Y: number }[] = [];
-                        for (var j = 0; j < ink.length; j++) {
+                        ink.forEach(i => {
                             // (new x — oldx) + (oldxpoint * newWidt)/oldWidth 
-                            const newX = (doc.x - oldX) + (ink[j].X * doc._width) / oldWidth;
-                            const newY = (doc.y - oldY) + (ink[j].Y * doc._height) / oldHeight;
+                            const newX = ((doc.x || 0) - oldX) + (i.X * (doc._width || 0)) / oldWidth;
+                            const newY = ((doc.y || 0) - oldY) + (i.Y * (doc._height || 0)) / oldHeight;
                             newPoints.push({ X: newX, Y: newY });
-                        }
+                        });
                         doc.data = new InkField(newPoints);
                     }
                 }
@@ -191,11 +190,11 @@ export default class FormatShapePane extends AntimodeMenu {
                 if (ink) {
 
                     const newPoints: { X: number, Y: number }[] = [];
-                    for (var i = 0; i < ink.length; i++) {
-                        const newX = Math.cos(angle) * (ink[i].X - _centerPoints[index].X) - Math.sin(angle) * (ink[i].Y - _centerPoints[index].Y) + _centerPoints[index].X;
-                        const newY = Math.sin(angle) * (ink[i].X - _centerPoints[index].X) + Math.cos(angle) * (ink[i].Y - _centerPoints[index].Y) + _centerPoints[index].Y;
+                    ink.forEach(i => {
+                        const newX = Math.cos(angle) * (i.X - _centerPoints[index].X) - Math.sin(angle) * (i.Y - _centerPoints[index].Y) + _centerPoints[index].X;
+                        const newY = Math.sin(angle) * (i.X - _centerPoints[index].X) + Math.cos(angle) * (i.Y - _centerPoints[index].Y) + _centerPoints[index].Y;
                         newPoints.push({ X: newX, Y: newY });
-                    }
+                    });
                     doc.data = new InkField(newPoints);
                     const xs = newPoints.map(p => p.X);
                     const ys = newPoints.map(p => p.Y);
@@ -395,12 +394,12 @@ export default class FormatShapePane extends AntimodeMenu {
     @computed get widInput() { return this.inputBox("wid", this.shapeWid, (val: string) => this.shapeWid = val); }
     @computed get rotInput() { return this.inputBoxDuo("rot", this.shapeRot, (val: string) => { this.rotate(Number(val) - Number(this.shapeRot)); this.shapeRot = val; return true; }, "∠:", "rot", this.shapeRot, (val: string) => this.shapeRot = val, ""); }
 
-    @computed get XpsInput() { return this.inputBoxDuo("Xps", this.shapeXps, (val: string) => this.shapeXps = val, "X:", "Yps", this.shapeYps, (val: string) => this.shapeYps = val, "Y:"); }
     @computed get YpsInput() { return this.inputBox("Yps", this.shapeYps, (val: string) => this.shapeYps = val); }
 
     @computed get controlPoints() { return this.controlPointsButton(); }
     @computed get lockRatio() { return this.lockRatioButton(); }
     @computed get rotate90() { return this.rotate90Button(); }
+    @computed get XpsInput() { return this.inputBoxDuo("Xps", this.shapeXps, (val: string) => this.shapeXps = val, "X:", "Yps", this.shapeYps, (val: string) => this.shapeYps = val, "Y:"); }
 
 
     @computed get propertyGroupItems() {
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
new file mode 100644
index 000000000..74f32275a
--- /dev/null
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -0,0 +1,620 @@
+.propertiesView {
+
+    background-color: rgb(205, 205, 205);
+    height: 100%;
+    font-family: "Noto Sans";
+    cursor: auto;
+
+    overflow-x: visible;
+    overflow-y: visible;
+
+    .propertiesView-title {
+        background-color: rgb(159, 159, 159);
+        text-align: center;
+        padding-top: 12px;
+        padding-bottom: 12px;
+        display: flex;
+        font-size: 18px;
+        font-weight: bold;
+        justify-content: center;
+
+        .propertiesView-title-icon {
+            width: 20px;
+            height: 20px;
+            padding-left: 38px;
+            margin-top: -5px;
+            right: 19;
+            position: absolute;
+
+            &:hover {
+                color: grey;
+                cursor: pointer;
+            }
+
+        }
+
+    }
+
+    .propertiesView-name {
+        border-bottom: 1px solid black;
+        padding: 8.5px;
+        font-size: 12.5px;
+
+        &:hover {
+            cursor: pointer;
+        }
+    }
+
+    .propertiesView-settings {
+        border-bottom: 1px solid black;
+        //padding: 8.5px;
+        font-size: 12.5px;
+        font-weight: bold;
+
+        .propertiesView-settings-title {
+            font-weight: bold;
+            font-size: 12.5px;
+            padding: 4px;
+            display: flex;
+            color: white;
+            padding-left: 8px;
+            background-color: rgb(51, 51, 51);
+
+            .propertiesView-settings-title-icon {
+                float: right;
+                right: 0;
+                position: absolute;
+                margin-left: 2px;
+                margin-right: 9px;
+
+                &:hover {
+                    cursor: pointer;
+                }
+            }
+        }
+
+        .propertiesView-settings-content {
+            margin-left: 12px;
+            padding-bottom: 10px;
+            padding-top: 8px;
+        }
+
+    }
+
+    .propertiesView-sharing {
+        border-bottom: 1px solid black;
+        //padding: 8.5px;
+
+        .propertiesView-sharing-title {
+            font-weight: bold;
+            font-size: 12.5px;
+            padding: 4px;
+            display: flex;
+            color: white;
+            padding-left: 8px;
+            background-color: rgb(51, 51, 51);
+
+            .propertiesView-sharing-title-icon {
+                float: right;
+                right: 0;
+                position: absolute;
+                margin-left: 2px;
+                margin-right: 9px;
+
+                &:hover {
+                    cursor: pointer;
+                }
+            }
+        }
+
+        .propertiesView-sharing-content {
+            font-size: 10px;
+            padding: 10px;
+            margin-left: 5px;
+        }
+    }
+
+    .propertiesView-appearance {
+        border-bottom: 1px solid black;
+        //padding: 8.5px;
+
+        .propertiesView-appearance-title {
+            font-weight: bold;
+            font-size: 12.5px;
+            padding: 4px;
+            display: flex;
+            color: white;
+            padding-left: 8px;
+            background-color: rgb(51, 51, 51);
+
+            .propertiesView-appearance-title-icon {
+                float: right;
+                right: 0;
+                position: absolute;
+                margin-left: 2px;
+                margin-right: 9px;
+
+                &:hover {
+                    cursor: pointer;
+                }
+            }
+        }
+
+        .propertiesView-appearance-content {
+            font-size: 10px;
+            padding: 10px;
+            margin-left: 5px;
+        }
+    }
+
+    .propertiesView-transform {
+        border-bottom: 1px solid black;
+        //padding: 8.5px;
+
+        .propertiesView-transform-title {
+            font-weight: bold;
+            font-size: 12.5px;
+            padding: 4px;
+            display: flex;
+            color: white;
+            padding-left: 8px;
+            background-color: rgb(51, 51, 51);
+
+            .propertiesView-transform-title-icon {
+                float: right;
+                right: 0;
+                position: absolute;
+                margin-left: 2px;
+                margin-right: 9px;
+
+                &:hover {
+                    cursor: pointer;
+                }
+            }
+        }
+
+        .propertiesView-transform-content {
+            font-size: 10px;
+            padding: 10px;
+            margin-left: 5px;
+        }
+    }
+
+    .notify-button {
+        padding: 2px;
+        width: 12px;
+        height: 12px;
+        background-color: black;
+        border-radius: 10px;
+        padding-left: 2px;
+        padding-right: 2px;
+        margin-top: 2px;
+        margin-left: 3px;
+
+        .notify-button-icon {
+            width: 6px;
+            height: 6.5px;
+            margin-left: .5px;
+        }
+
+        &:hover {
+            background-color: rgb(158, 158, 158);
+            cursor: pointer;
+        }
+    }
+
+    .expansion-button-icon {
+        width: 11px;
+        height: 11px;
+        color: black;
+        margin-left: 27px;
+
+        &:hover {
+            color: rgb(131, 131, 131);
+            cursor: pointer;
+        }
+    }
+
+    .propertiesView-sharingTable {
+
+        border: 1px solid black;
+        padding: 5px;
+        border-radius: 6px;
+        /* width: 170px; */
+        margin-right: 10px;
+        background-color: #ececec;
+        max-height: 130px;
+        overflow-y: scroll;
+
+        .propertiesView-sharingTable-item {
+
+            display: flex;
+            padding: 3px;
+            align-items: center;
+            border-bottom: 0.5px solid grey;
+
+            &:hover .propertiesView-sharingTable-item-name {
+                overflow-x: unset;
+                white-space: unset;
+                overflow-wrap: break-word;
+            }
+
+            .propertiesView-sharingTable-item-name {
+                font-weight: bold;
+                width: 80px;
+                overflow-x: hidden;
+                display: inline-block;
+                text-overflow: ellipsis;
+                white-space: nowrap;
+            }
+
+            .propertiesView-sharingTable-item-permission {
+                display: flex;
+                right: 34;
+                float: right;
+                position: absolute;
+
+                .permissions-select {
+                    z-index: 1;
+                    border: none;
+                    background-color: inherit;
+                    width: 75px;
+                    text-align: justify; // for Edge
+                    text-align-last: end;
+
+                    &:hover {
+                        cursor: pointer;
+                    }
+                }
+            }
+
+            &:last-child {
+                border-bottom: none;
+            }
+        }
+    }
+
+    .propertiesView-fields {
+        border-bottom: 1px solid black;
+        //padding: 8.5px;
+
+        .propertiesView-fields-title {
+            font-weight: bold;
+            font-size: 12.5px;
+            padding: 4px;
+            display: flex;
+            color: white;
+            padding-left: 8px;
+            background-color: rgb(51, 51, 51);
+
+            .propertiesView-fields-title-name {
+                font-size: 12.5px;
+                font-weight: bold;
+                white-space: nowrap;
+                width: 35px;
+                display: flex;
+            }
+
+            .propertiesView-fields-title-icon {
+                float: right;
+                right: 0;
+                position: absolute;
+                margin-left: 2px;
+                margin-right: 9px;
+
+                &:hover {
+                    cursor: pointer;
+                }
+            }
+        }
+
+        .propertiesView-fields-checkbox {
+            float: right;
+            height: 20px;
+            margin-top: -9px;
+
+            .propertiesView-fields-checkbox-text {
+                font-size: 7px;
+                margin-top: -10px;
+                margin-left: 6px;
+            }
+        }
+
+        .propertiesView-fields-content {
+            font-size: 10px;
+            margin-left: 2px;
+            padding: 10px;
+
+            &:hover {
+                cursor: pointer;
+            }
+        }
+    }
+
+    .field {
+        display: flex;
+        font-size: 7px;
+        background-color: #e8e8e8;
+        padding-right: 3px;
+        border: 0.5px solid grey;
+        border-radius: 5px;
+        padding-left: 3px;
+    }
+
+    .uneditable-field {
+        display: flex;
+        overflow-y: visible;
+        margin-bottom: 2px;
+
+        &:hover {
+            cursor: auto;
+        }
+    }
+
+    .propertiesView-layout {
+
+        .propertiesView-layout-title {
+            font-weight: bold;
+            font-size: 12.5px;
+            padding: 4px;
+            display: flex;
+            color: white;
+            padding-left: 8px;
+            background-color: rgb(51, 51, 51);
+
+            .propertiesView-layout-title-icon {
+                float: right;
+                right: 0;
+                position: absolute;
+                margin-left: 2px;
+                margin-right: 9px;
+
+                &:hover {
+                    cursor: pointer;
+                }
+            }
+        }
+
+        .propertiesView-layout-content {
+            overflow: hidden;
+            padding: 10px;
+        }
+
+    }
+}
+
+.inking-button {
+
+    display: flex;
+
+    .inking-button-points {
+        background-color: #333333;
+        padding: 7px;
+        border-radius: 7px;
+        margin-right: 32px;
+        width: 32;
+        height: 32;
+        padding-top: 9px;
+        margin-left: 18px;
+
+        &:hover {
+            background: rgb(131, 131, 131);
+            transform: scale(1.05);
+            cursor: pointer;
+        }
+    }
+
+    .inking-button-lock {
+        background-color: #333333;
+        padding: 7px;
+        border-radius: 7px;
+        margin-right: 32px;
+        width: 32;
+        height: 32;
+        padding-top: 9px;
+        padding-left: 10px;
+
+        &:hover {
+            background: rgb(131, 131, 131);
+            transform: scale(1.05);
+            cursor: pointer;
+        }
+    }
+
+    .inking-button-rotate {
+        background-color: #333333;
+        padding: 7px;
+        border-radius: 7px;
+        width: 32;
+        height: 32;
+        padding-top: 9px;
+        padding-left: 10px;
+
+        &:hover {
+            background: rgb(131, 131, 131);
+            transform: scale(1.05);
+            cursor: pointer;
+        }
+    }
+}
+
+.inputBox-duo {
+    display: flex;
+}
+
+.inputBox {
+
+    margin-top: 10px;
+    display: flex;
+    height: 19px;
+    margin-right: 15px;
+
+    .inputBox-title {
+        font-size: 12px;
+        padding-right: 5px;
+    }
+
+    .inputBox-input {
+        font-size: 10px;
+        width: 50px;
+        margin-right: 1px;
+        border-radius: 3px;
+
+        &:hover {
+            cursor: pointer;
+        }
+    }
+
+    .inputBox-button {
+
+        .inputBox-button-up {
+            background-color: #333333;
+            height: 9px;
+            padding-left: 3px;
+            padding-right: 3px;
+            padding-top: 1px;
+            padding-bottom: 1px;
+            border-radius: 1.5px;
+
+            &:hover {
+                background: rgb(131, 131, 131);
+                transform: scale(1.05);
+                cursor: pointer;
+            }
+        }
+
+        .inputBox-button-down {
+            background-color: #333333;
+            height: 9px;
+            padding-left: 3px;
+            padding-right: 3px;
+            padding-top: 1px;
+            padding-bottom: 1px;
+            border-radius: 1.5px;
+
+            &:hover {
+                background: rgb(131, 131, 131);
+                transform: scale(1.05);
+                cursor: pointer;
+            }
+        }
+
+    }
+}
+
+.color-palette {
+    width: 160px;
+    height: 360;
+}
+
+.strokeAndFill {
+    display: flex;
+    margin-top: 10px;
+
+    .fill {
+        margin-right: 40px;
+        display: flex;
+        padding-bottom: 7px;
+        margin-left: 35px;
+
+        .fill-title {
+            font-size: 12px;
+            margin-right: 2px;
+        }
+
+        .fill-button {
+            padding-top: 2px;
+            margin-top: -1px;
+        }
+    }
+
+    .stroke {
+        display: flex;
+
+        .stroke-title {
+            font-size: 12px;
+        }
+
+        .stroke-button {
+            padding-top: 2px;
+            margin-left: 2px;
+            margin-top: -1px;
+        }
+    }
+}
+
+.widthAndDash {
+
+    .width {
+        .width-top {
+            display: flex;
+
+            .width-title {
+                font-size: 12;
+                margin-right: 20px;
+                margin-left: 35px;
+                text-align: center;
+            }
+
+            .width-input {
+                margin-right: 30px;
+                margin-top: -10px;
+            }
+        }
+
+        .width-range {
+            margin-right: 1px;
+            margin-bottom: 6;
+        }
+    }
+
+    .arrows {
+
+        display: flex;
+        margin-bottom: 3px;
+
+        .arrows-head {
+
+            display: flex;
+            margin-right: 35px;
+
+            .arrows-head-title {
+                font-size: 10;
+            }
+
+            .arrows-head-input {
+                margin-left: 6px;
+                margin-top: 2px;
+            }
+        }
+
+        .arrows-tail {
+            display: flex;
+
+            .arrows-tail-title {
+                font-size: 10;
+            }
+
+            .arrows-tail-input {
+                margin-left: 6px;
+                margin-top: 2px;
+            }
+        }
+    }
+
+    .dashed {
+
+        display: flex;
+        margin-left: 74px;
+        margin-bottom: 6px;
+
+        .dashed-title {
+            font-size: 10;
+        }
+
+        .dashed-input {
+            margin-left: 6px;
+            margin-top: 2px;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
new file mode 100644
index 000000000..35c7fd425
--- /dev/null
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -0,0 +1,858 @@
+import React = require("react");
+import { observer } from "mobx-react";
+import "./PropertiesView.scss";
+import { observable, action, computed, runInAction } from "mobx";
+import { Doc, Field, DocListCast, WidthSym, HeightSym, AclSym, AclPrivate, AclReadonly, AclAddonly, AclEdit, AclAdmin, Opt } from "../../../../fields/Doc";
+import { DocumentView } from "../../nodes/DocumentView";
+import { ComputedField } from "../../../../fields/ScriptField";
+import { EditableView } from "../../EditableView";
+import { KeyValueBox } from "../../nodes/KeyValueBox";
+import { Cast, NumCast, StrCast } from "../../../../fields/Types";
+import { listSpec } from "../../../../fields/Schema";
+import { ContentFittingDocumentView } from "../../nodes/ContentFittingDocumentView";
+import { returnFalse, returnOne, emptyFunction, emptyPath, returnTrue, returnZero, returnEmptyFilter, Utils } from "../../../../Utils";
+import { Id } from "../../../../fields/FieldSymbols";
+import { Transform } from "../../../util/Transform";
+import { PropertiesButtons } from "../../PropertiesButtons";
+import { SelectionManager } from "../../../util/SelectionManager";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { Tooltip, Checkbox, Divider } from "@material-ui/core";
+import SharingManager from "../../../util/SharingManager";
+import { DocumentType } from "../../../documents/DocumentTypes";
+import FormatShapePane from "./FormatShapePane";
+import { SharingPermissions, GetEffectiveAcl } from "../../../../fields/util";
+import { InkField } from "../../../../fields/InkField";
+import { undoBatch } from "../../../util/UndoManager";
+import { ColorState, SketchPicker } from "react-color";
+import AntimodeMenu from "../../AntimodeMenu";
+import "./FormatShapePane.scss";
+import { discovery_v1 } from "googleapis";
+import { PresBox } from "../../nodes/PresBox";
+import { DocumentManager } from "../../../util/DocumentManager";
+
+
+interface PropertiesViewProps {
+    width: number;
+    height: number;
+    renderDepth: number;
+    ScreenToLocalTransform: () => Transform;
+    onDown: (event: any) => void;
+}
+
+@observer
+export class PropertiesView extends React.Component<PropertiesViewProps> {
+
+    @computed get MAX_EMBED_HEIGHT() { return 200; }
+
+    @computed get selectedDocumentView() {
+        if (SelectionManager.SelectedDocuments().length) {
+            return SelectionManager.SelectedDocuments()[0];
+        } else if (PresBox.Instance) {
+            const presSlide = PresBox.Instance._selectedArray[0];
+            const view = DocumentManager.Instance.getDocumentView(presSlide);
+            if (view) return view;
+        } else { return undefined; }
+    }
+    @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; }
+    @computed get dataDoc() { return this.selectedDocumentView?.dataDoc; }
+
+    @observable layoutFields: boolean = false;
+
+    @observable openActions: boolean = true;
+    @observable openSharing: boolean = true;
+    @observable openFields: boolean = true;
+    @observable openLayout: boolean = true;
+    @observable openAppearance: boolean = true;
+    @observable openTransform: boolean = true;
+
+    @computed get isInk() { return this.selectedDoc?.type === DocumentType.INK; }
+
+    @action
+    rtfWidth = () => {
+        if (this.selectedDoc) {
+            return Math.min(this.selectedDoc?.[WidthSym](), this.props.width - 20);
+        } else {
+            return 0;
+        }
+    }
+    @action
+    rtfHeight = () => {
+        if (this.selectedDoc) {
+            return this.rtfWidth() <= this.selectedDoc?.[WidthSym]() ? Math.min(this.selectedDoc?.[HeightSym](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT;
+        } else {
+            return 0;
+        }
+    }
+
+    @action
+    docWidth = () => {
+        if (this.selectedDoc) {
+            const layoutDoc = this.selectedDoc;
+            const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]());
+            if (aspect) return Math.min(layoutDoc[WidthSym](), Math.min(this.MAX_EMBED_HEIGHT / aspect, this.props.width - 20));
+            return NumCast(layoutDoc._nativeWidth) ? Math.min(layoutDoc[WidthSym](), this.props.width - 20) : this.props.width - 20;
+        } else {
+            return 0;
+        }
+    }
+
+    @action
+    docHeight = () => {
+        if (this.selectedDoc && this.dataDoc) {
+            const layoutDoc = this.selectedDoc;
+            return Math.max(70, Math.min(this.MAX_EMBED_HEIGHT, (() => {
+                const aspect = NumCast(layoutDoc._nativeHeight, layoutDoc._fitWidth ? 0 : layoutDoc[HeightSym]()) / NumCast(layoutDoc._nativeWidth, layoutDoc._fitWidth ? 1 : layoutDoc[WidthSym]());
+                if (aspect) return this.docWidth() * aspect;
+                return layoutDoc._fitWidth ? (!this.dataDoc._nativeHeight ? NumCast(this.props.height) :
+                    Math.min(this.docWidth() * NumCast(layoutDoc.scrollHeight, NumCast(layoutDoc._nativeHeight)) / NumCast(layoutDoc._nativeWidth,
+                        NumCast(this.props.height)))) :
+                    NumCast(layoutDoc._height) ? NumCast(layoutDoc._height) : 50;
+            })()));
+        } else {
+            return 0;
+        }
+    }
+
+    @computed get expandedField() {
+        if (this.dataDoc && this.selectedDoc) {
+            const ids: { [key: string]: string } = {};
+            const doc = this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc;
+            doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key));
+            const rows: JSX.Element[] = [];
+            for (const key of Object.keys(ids).slice().sort()) {
+                const contents = doc[key];
+                if (key[0] === "#") {
+                    rows.push(<div style={{ display: "flex", overflowY: "visible", marginBottom: "2px" }} key={key}>
+                        <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key}</span>
+                    &nbsp;
+                </div>);
+                } else {
+                    let contentElement: (JSX.Element | null)[] | JSX.Element = [];
+                    contentElement = <EditableView key="editableView"
+                        contents={contents !== undefined ? Field.toString(contents as Field) : "null"}
+                        height={13}
+                        fontSize={10}
+                        GetValue={() => Field.toKeyValueString(doc, key)}
+                        SetValue={(value: string) => KeyValueBox.SetField(doc, key, value, true)}
+                    />;
+                    rows.push(<div style={{ display: "flex", overflowY: "visible", marginBottom: "-1px" }} key={key}>
+                        <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key + ":"}</span>
+                        &nbsp;
+                        {contentElement}
+                    </div>);
+                }
+            }
+            rows.push(<div className="field" key={"newKeyValue"} style={{ marginTop: "3px" }}>
+                <EditableView
+                    key="editableView"
+                    contents={"add key:value or #tags"}
+                    height={13}
+                    fontSize={10}
+                    GetValue={() => ""}
+                    SetValue={this.setKeyValue} />
+            </div>);
+            return rows;
+        }
+    }
+
+    @computed get noviceFields() {
+        if (this.dataDoc && this.selectedDoc) {
+            const ids: { [key: string]: string } = {};
+            const doc = this.dataDoc;
+            doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key));
+            const rows: JSX.Element[] = [];
+            for (const key of Object.keys(ids).slice().sort()) {
+                if (key[0] === key[0].toUpperCase() || key[0] === "#" || key === "author" || key === "creationDate" || key.indexOf("lastModified") !== -1) {
+                    const contents = doc[key];
+                    if (key[0] === "#") {
+                        rows.push(<div className="uneditable-field" key={key}>
+                            <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key}</span>
+                    &nbsp;
+                </div>);
+                    } else {
+                        const value = Field.toString(contents as Field);
+                        if (key === "author" || key === "creationDate" || key.indexOf("lastModified") !== -1) {
+                            rows.push(<div className="uneditable-field" key={key}>
+                                <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key + ": "}</span>
+                                <div style={{ whiteSpace: "nowrap", overflowX: "hidden" }}>{value}</div>
+                            </div>);
+                        } else {
+                            let contentElement: (JSX.Element | null)[] | JSX.Element = [];
+                            contentElement = <EditableView key="editableView"
+                                contents={contents !== undefined ? Field.toString(contents as Field) : "null"}
+                                height={13}
+                                fontSize={10}
+                                GetValue={() => Field.toKeyValueString(doc, key)}
+                                SetValue={(value: string) => KeyValueBox.SetField(doc, key, value, true)}
+                            />;
+
+                            rows.push(<div style={{ display: "flex", overflowY: "visible", marginBottom: "-1px" }} key={key}>
+                                <span style={{ fontWeight: "bold", whiteSpace: "nowrap" }}>{key + ":"}</span>
+                            &nbsp;
+                            {contentElement}
+                            </div>);
+                        }
+                    }
+                }
+            }
+            rows.push(<div className="field" key={"newKeyValue"} style={{ marginTop: "3px" }}>
+                <EditableView
+                    key="editableView"
+                    contents={"add key:value or #tags"}
+                    height={13}
+                    fontSize={10}
+                    GetValue={() => ""}
+                    SetValue={this.setKeyValue} />
+            </div>);
+            return rows;
+        }
+    }
+
+
+    setKeyValue = (value: string) => {
+        if (this.selectedDoc && this.dataDoc) {
+            const doc = this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc;
+            if (value.indexOf(":") !== -1) {
+                const newVal = value[0].toUpperCase() + value.substring(1, value.length);
+                KeyValueBox.SetField(doc, newVal.substring(0, newVal.indexOf(":")), newVal.substring(newVal.indexOf(":") + 1, newVal.length), true);
+                return true;
+            } else if (value[0] === "#") {
+                const newVal = value + `:'${value}'`;
+                KeyValueBox.SetField(doc, newVal.substring(0, newVal.indexOf(":")), newVal.substring(newVal.indexOf(":") + 1, newVal.length), true);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @computed get layoutPreview() {
+        if (this.selectedDoc) {
+            const layoutDoc = Doc.Layout(this.selectedDoc);
+            const panelHeight = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : this.docHeight;
+            const panelWidth = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : this.docWidth;
+            return <div style={{ display: "inline-block", height: panelHeight() }} key={this.selectedDoc[Id]}>
+                <ContentFittingDocumentView
+                    Document={layoutDoc}
+                    DataDoc={this.dataDoc}
+                    LibraryPath={emptyPath}
+                    renderDepth={this.props.renderDepth + 1}
+                    rootSelected={returnFalse}
+                    treeViewDoc={undefined}
+                    backgroundColor={() => "lightgrey"}
+                    fitToBox={false}
+                    FreezeDimensions={true}
+                    NativeWidth={layoutDoc.type ===
+                        StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : returnZero}
+                    NativeHeight={layoutDoc.type ===
+                        StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : returnZero}
+                    PanelWidth={panelWidth}
+                    PanelHeight={panelHeight}
+                    focus={returnFalse}
+                    ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+                    docFilters={returnEmptyFilter}
+                    ContainingCollectionDoc={undefined}
+                    ContainingCollectionView={undefined}
+                    addDocument={returnFalse}
+                    moveDocument={undefined}
+                    removeDocument={returnFalse}
+                    parentActive={() => false}
+                    whenActiveChanged={emptyFunction}
+                    addDocTab={returnFalse}
+                    pinToPres={emptyFunction}
+                    bringToFront={returnFalse}
+                    ContentScaling={returnOne}
+                    dontRegisterView={true}
+                />
+            </div>;
+        } else {
+            return null;
+        }
+    }
+
+    getPermissionsSelect(user: string) {
+        return <select className="permissions-select"
+            onChange={e => SharingManager.Instance.shareFromPropertiesSidebar(user, e.currentTarget.value as SharingPermissions, this.selectedDoc!)}>
+            {Object.values(SharingPermissions).map(permission => {
+                return (
+                    <option key={permission} value={permission} selected={this.selectedDoc![`ACL-${user.replace(".", "_")}`] === permission}>
+                        {permission}
+                    </option>);
+            })}
+        </select>;
+    }
+
+    @computed get notifyIcon() {
+        return <Tooltip title={<><div className="dash-tooltip">Notify with message</div></>}>
+            <div className="notify-button">
+                <FontAwesomeIcon className="notify-button-icon" icon="bell" color="white" size="sm" />
+            </div>
+        </Tooltip>;
+    }
+
+    @computed get expansionIcon() {
+        return <Tooltip title={<><div className="dash-tooltip">{"Show more permissions"}</div></>}>
+            <div className="expansion-button" onPointerDown={() => {
+                if (this.selectedDocumentView) {
+                    SharingManager.Instance.open(this.selectedDocumentView);
+                }
+            }}>
+                <FontAwesomeIcon className="expansion-button-icon" icon="ellipsis-h" color="black" size="sm" />
+            </div>
+        </Tooltip>;
+    }
+
+    sharingItem(name: string, effectiveAcl: symbol, permission?: string) {
+        return <div className="propertiesView-sharingTable-item">
+            <div className="propertiesView-sharingTable-item-name" style={{ width: name !== "Me" ? "70px" : "80px" }}> {name} </div>
+            {name !== "Me" ? this.notifyIcon : null}
+            <div className="propertiesView-sharingTable-item-permission">
+                {effectiveAcl === AclAdmin && permission !== "Owner" ? this.getPermissionsSelect(name) : permission}
+                {permission === "Owner" ? this.expansionIcon : null}
+            </div>
+        </div>;
+    }
+
+    @computed get sharingTable() {
+        const AclMap = new Map<symbol, string>([
+            [AclPrivate, SharingPermissions.None],
+            [AclReadonly, SharingPermissions.View],
+            [AclAddonly, SharingPermissions.Add],
+            [AclEdit, SharingPermissions.Edit],
+            [AclAdmin, SharingPermissions.Admin]
+        ]);
+
+        const effectiveAcl = GetEffectiveAcl(this.selectedDoc!);
+        const tableEntries = [];
+
+        if (this.selectedDoc![AclSym]) {
+            for (const [key, value] of Object.entries(this.selectedDoc![AclSym])) {
+                const name = key.substring(4).replace("_", ".");
+                if (name !== Doc.CurrentUserEmail && name !== this.selectedDoc!.author) tableEntries.push(this.sharingItem(name, effectiveAcl, AclMap.get(value)!));
+            }
+        }
+
+        tableEntries.unshift(this.sharingItem("Me", effectiveAcl, Doc.CurrentUserEmail === this.selectedDoc!.author ? "Owner" : StrCast(this.selectedDoc![`ACL-${Doc.CurrentUserEmail.replace(".", "_")}`])));
+        if (Doc.CurrentUserEmail !== this.selectedDoc!.author) tableEntries.unshift(this.sharingItem(StrCast(this.selectedDoc!.author), effectiveAcl, "Owner"));
+
+        return <div className="propertiesView-sharingTable">
+            {tableEntries}
+        </div>;
+    }
+
+    @computed get fieldsCheckbox() {
+        return <Checkbox
+            color="primary"
+            onChange={this.toggleCheckbox}
+            checked={this.layoutFields}
+        />;
+    }
+
+    @action
+    toggleCheckbox = () => {
+        this.layoutFields = !this.layoutFields;
+    }
+
+    @computed get editableTitle() {
+        return <EditableView
+            key="editableView"
+            contents={StrCast(this.selectedDoc?.title)}
+            height={25}
+            fontSize={14}
+            GetValue={() => StrCast(this.selectedDoc?.title)}
+            SetValue={this.setTitle} />;
+    }
+
+    @action
+    setTitle = (value: string) => {
+        if (this.dataDoc) {
+            this.selectedDoc && (this.selectedDoc.title = value);
+            KeyValueBox.SetField(this.dataDoc, "title", value, true);
+            return true;
+        }
+        return false;
+    }
+
+
+
+
+
+
+
+
+
+    @undoBatch
+    @action
+    rotate = (angle: number) => {
+        const _centerPoints: { X: number, Y: number }[] = [];
+        if (this.selectedDoc) {
+            const doc = this.selectedDoc;
+            if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) {
+                const ink = Cast(doc.data, InkField)?.inkData;
+                if (ink) {
+                    const xs = ink.map(p => p.X);
+                    const ys = ink.map(p => p.Y);
+                    const left = Math.min(...xs);
+                    const top = Math.min(...ys);
+                    const right = Math.max(...xs);
+                    const bottom = Math.max(...ys);
+                    _centerPoints.push({ X: left, Y: top });
+                }
+            }
+
+            var index = 0;
+            if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) {
+                doc.rotation = Number(doc.rotation) + Number(angle);
+                const ink = Cast(doc.data, InkField)?.inkData;
+                if (ink) {
+
+                    const newPoints: { X: number, Y: number }[] = [];
+                    for (var i = 0; i < ink.length; i++) {
+                        const newX = Math.cos(angle) * (ink[i].X - _centerPoints[index].X) - Math.sin(angle) * (ink[i].Y - _centerPoints[index].Y) + _centerPoints[index].X;
+                        const newY = Math.sin(angle) * (ink[i].X - _centerPoints[index].X) + Math.cos(angle) * (ink[i].Y - _centerPoints[index].Y) + _centerPoints[index].Y;
+                        newPoints.push({ X: newX, Y: newY });
+                    }
+                    doc.data = new InkField(newPoints);
+                    const xs = newPoints.map(p => p.X);
+                    const ys = newPoints.map(p => p.Y);
+                    const left = Math.min(...xs);
+                    const top = Math.min(...ys);
+                    const right = Math.max(...xs);
+                    const bottom = Math.max(...ys);
+
+                    doc._height = (bottom - top);
+                    doc._width = (right - left);
+                }
+                index++;
+            }
+        }
+    }
+
+    @observable _controlBtn: boolean = false;
+    @observable _lock: boolean = false;
+
+    @computed
+    get controlPointsButton() {
+        return <div className="inking-button">
+            <Tooltip title={<><div className="dash-tooltip">{"Edit points"}</div></>}>
+                <div className="inking-button-points" onPointerDown={action(() => this._controlBtn = !this._controlBtn)} style={{ backgroundColor: this._controlBtn ? "black" : "" }}>
+                    <FontAwesomeIcon icon="bezier-curve" color="white" size="lg" />
+                </div>
+            </Tooltip>
+            <Tooltip title={<><div className="dash-tooltip">{this._lock ? "Unlock points" : "Lock points"}</div></>}>
+                <div className="inking-button-lock" onPointerDown={action(() => this._lock = !this._lock)} >
+                    <FontAwesomeIcon icon={this._lock ? "unlock" : "lock"} color="white" size="lg" />
+                </div>
+            </Tooltip>
+            <Tooltip title={<><div className="dash-tooltip">{"Rotate 90˚"}</div></>}>
+                <div className="inking-button-rotate" onPointerDown={action(() => this.rotate(Math.PI / 2))}>
+                    <FontAwesomeIcon icon="undo" color="white" size="lg" />
+                </div>
+            </Tooltip>
+        </div>;
+    }
+
+    inputBox = (key: string, value: any, setter: (val: string) => {}, title: string) => {
+        return <div className="inputBox"
+            style={{
+                marginRight: title === "X:" ? "19px" : "",
+                marginLeft: title === "∠:" ? "39px" : ""
+            }}>
+            <div className="inputBox-title"> {title} </div>
+            <input className="inputBox-input"
+                type="text" value={value}
+                onChange={e => setter(e.target.value)} />
+            <div className="inputBox-button">
+                <div className="inputBox-button-up" key="up2"
+                    onPointerDown={undoBatch(action(() => this.upDownButtons("up", key)))} >
+                    <FontAwesomeIcon icon="caret-up" color="white" size="sm" />
+                </div>
+                <div className="inputbox-Button-down" key="down2"
+                    onPointerDown={undoBatch(action(() => this.upDownButtons("down", key)))} >
+                    <FontAwesomeIcon icon="caret-down" color="white" size="sm" />
+                </div>
+            </div>
+        </div>;
+    }
+
+    inputBoxDuo = (key: string, value: any, setter: (val: string) => {}, title1: string, key2: string, value2: any, setter2: (val: string) => {}, title2: string) => {
+        return <div className="inputBox-duo">
+            {this.inputBox(key, value, setter, title1)}
+            {title2 === "" ? (null) : this.inputBox(key2, value2, setter2, title2)}
+        </div>;
+    }
+
+    @action
+    upDownButtons = (dirs: string, field: string) => {
+        switch (field) {
+            case "rot": this.rotate((dirs === "up" ? .1 : -.1)); break;
+            // case "rot": this.selectedInk?.forEach(i => i.rootDoc.rotation = NumCast(i.rootDoc.rotation) + (dirs === "up" ? 0.1 : -0.1)); break;
+            case "Xps": this.selectedDoc && (this.selectedDoc.x = NumCast(this.selectedDoc?.x) + (dirs === "up" ? 10 : -10)); break;
+            case "Yps": this.selectedDoc && (this.selectedDoc.y = NumCast(this.selectedDoc?.y) + (dirs === "up" ? 10 : -10)); break;
+            case "stk": this.selectedDoc && (this.selectedDoc.strokeWidth = NumCast(this.selectedDoc?.strokeWidth) + (dirs === "up" ? .1 : -.1)); break;
+            case "wid":
+                const oldWidth = NumCast(this.selectedDoc?._width);
+                const oldHeight = NumCast(this.selectedDoc?._height);
+                const oldX = NumCast(this.selectedDoc?.x);
+                const oldY = NumCast(this.selectedDoc?.y);
+                this.selectedDoc && (this.selectedDoc._width = oldWidth + (dirs === "up" ? 10 : - 10));
+                this._lock && this.selectedDoc && (this.selectedDoc._height = (NumCast(this.selectedDoc?._width) / oldWidth * NumCast(this.selectedDoc?._height)));
+                const doc = this.selectedDoc;
+                if (doc?.type === DocumentType.INK && doc.x && doc.y && doc._height && doc._width) {
+                    console.log(doc.x, doc.y, doc._height, doc._width);
+                    const ink = Cast(doc.data, InkField)?.inkData;
+                    console.log(ink);
+                    if (ink) {
+                        const newPoints: { X: number, Y: number }[] = [];
+                        for (var j = 0; j < ink.length; j++) {
+                            // (new x — oldx) + (oldxpoint * newWidt)/oldWidth 
+                            const newX = (NumCast(doc.x) - oldX) + (ink[j].X * NumCast(doc._width)) / oldWidth;
+                            const newY = (NumCast(doc.y) - oldY) + (ink[j].Y * NumCast(doc._height)) / oldHeight;
+                            newPoints.push({ X: newX, Y: newY });
+                        }
+                        doc.data = new InkField(newPoints);
+                    }
+                }
+                break;
+            case "hgt":
+                const oWidth = NumCast(this.selectedDoc?._width);
+                const oHeight = NumCast(this.selectedDoc?._height);
+                const oX = NumCast(this.selectedDoc?.x);
+                const oY = NumCast(this.selectedDoc?.y);
+                this.selectedDoc && (this.selectedDoc._height = oHeight + (dirs === "up" ? 10 : - 10));
+                this._lock && this.selectedDoc && (this.selectedDoc._width = (NumCast(this.selectedDoc?._height) / oHeight * NumCast(this.selectedDoc?._width)));
+                const docu = this.selectedDoc;
+                if (docu?.type === DocumentType.INK && docu.x && docu.y && docu._height && docu._width) {
+                    console.log(docu.x, docu.y, docu._height, docu._width);
+                    const ink = Cast(docu.data, InkField)?.inkData;
+                    console.log(ink);
+                    if (ink) {
+                        const newPoints: { X: number, Y: number }[] = [];
+                        for (var j = 0; j < ink.length; j++) {
+                            // (new x — oldx) + (oldxpoint * newWidt)/oldWidth 
+                            const newX = (NumCast(docu.x) - oX) + (ink[j].X * NumCast(docu._width)) / oWidth;
+                            const newY = (NumCast(docu.y) - oY) + (ink[j].Y * NumCast(docu._height)) / oHeight;
+                            newPoints.push({ X: newX, Y: newY });
+                        }
+                        docu.data = new InkField(newPoints);
+                    }
+                }
+                break;
+        }
+    }
+
+    getField(key: string) {
+        //if (this.selectedDoc) {
+        return Field.toString(this.selectedDoc[key] as Field);
+        // } else {
+        //     return undefined as Opt<string>;
+        // }
+    }
+
+    @computed get shapeXps() { return this.getField("x"); }
+    @computed get shapeYps() { return this.getField("y"); }
+    @computed get shapeRot() { return this.getField("rotation"); }
+    @computed get shapeHgt() { return this.getField("_height"); }
+    @computed get shapeWid() { return this.getField("_width"); }
+    set shapeXps(value) { this.selectedDoc && (this.selectedDoc.x = Number(value)); }
+    set shapeYps(value) { this.selectedDoc && (this.selectedDoc.y = Number(value)); }
+    set shapeRot(value) { this.selectedDoc && (this.selectedDoc.rotation = Number(value)); }
+    set shapeWid(value) {
+        const oldWidth = NumCast(this.selectedDoc?._width);
+        this.selectedDoc && (this.selectedDoc._width = Number(value));
+        this._lock && this.selectedDoc && (this.selectedDoc._height = (NumCast(this.selectedDoc?._width) * NumCast(this.selectedDoc?._height)) / oldWidth);
+    }
+    set shapeHgt(value) {
+        const oldHeight = NumCast(this.selectedDoc?._height);
+        this.selectedDoc && (this.selectedDoc._height = Number(value));
+        this._lock && this.selectedDoc && (this.selectedDoc._width = (NumCast(this.selectedDoc?._height) * NumCast(this.selectedDoc?._width)) / oldHeight);
+    }
+
+    @computed get hgtInput() { return this.inputBoxDuo("hgt", this.shapeHgt, (val: string) => this.shapeHgt = val, "H:", "wid", this.shapeWid, (val: string) => this.shapeWid = val, "W:"); }
+    @computed get XpsInput() { return this.inputBoxDuo("Xps", this.shapeXps, (val: string) => this.shapeXps = val, "X:", "Yps", this.shapeYps, (val: string) => this.shapeYps = val, "Y:"); }
+    @computed get rotInput() { return this.inputBoxDuo("rot", this.shapeRot, (val: string) => { this.rotate(Number(val) - Number(this.shapeRot)); this.shapeRot = val; return true; }, "∠:", "rot", this.shapeRot, (val: string) => this.shapeRot = val, ""); }
+
+    @observable private _fillBtn = false;
+    @observable private _lineBtn = false;
+
+    private _lastFill = "#D0021B";
+    private _lastLine = "#D0021B";
+    private _lastDash: any = "2";
+
+    @computed get colorFil() { const ccol = this.getField("fillColor") || ""; ccol && (this._lastFill = ccol); return ccol; }
+    @computed get colorStk() { const ccol = this.getField("color") || ""; ccol && (this._lastLine = ccol); return ccol; }
+    set colorFil(value) { value && (this._lastFill = value); this.selectedDoc && (this.selectedDoc.fillColor = value ? value : undefined); }
+    set colorStk(value) { value && (this._lastLine = value); this.selectedDoc && (this.selectedDoc.color = value ? value : undefined); }
+
+    colorButton(value: string, setter: () => {}) {
+        return <div className="color-button" key="color" onPointerDown={undoBatch(action(e => setter()))}>
+            <div className="color-button-preview" style={{
+                backgroundColor: value ?? "121212", width: 15, height: 15,
+                display: value === "" || value === "transparent" ? "none" : ""
+            }} />
+            {value === "" || value === "transparent" ? <p style={{ fontSize: 25, color: "red", marginTop: -14, position: "fixed" }}>☒</p> : ""}
+        </div>;
+    }
+
+    @undoBatch
+    @action
+    switchStk = (color: ColorState) => {
+        const val = String(color.hex);
+        this.colorStk = val;
+        return true;
+    }
+    @undoBatch
+    @action
+    switchFil = (color: ColorState) => {
+        const val = String(color.hex);
+        this.colorFil = val;
+        return true;
+    }
+
+    colorPicker(setter: (color: string) => {}, type: string) {
+        return <SketchPicker onChange={type === "stk" ? this.switchStk : this.switchFil}
+            presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505',
+                '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B',
+                '#FFFFFF', '#f1efeb', 'transparent']}
+            color={type === "stk" ? this.colorStk : this.colorFil} />;
+    }
+
+    @computed get fillButton() { return this.colorButton(this.colorFil, () => { this._fillBtn = !this._fillBtn; this._lineBtn = false; return true; }); }
+    @computed get lineButton() { return this.colorButton(this.colorStk, () => { this._lineBtn = !this._lineBtn; this._fillBtn = false; return true; }); }
+
+    @computed get fillPicker() { return this.colorPicker((color: string) => this.colorFil = color, "fil"); }
+    @computed get linePicker() { return this.colorPicker((color: string) => this.colorStk = color, "stk"); }
+
+    @computed get strokeAndFill() {
+        return <div>
+            <div key="fill" className="strokeAndFill">
+                <div className="fill">
+                    <div className="fill-title">Fill:</div>
+                    <div className="fill-button">{this.fillButton}</div>
+                </div>
+                <div className="stroke">
+                    <div className="stroke-title"> Stroke: </div>
+                    <div className="stroke-button">{this.lineButton}</div>
+                </div>
+            </div>
+            {this._fillBtn ? this.fillPicker : ""}
+            {this._lineBtn ? this.linePicker : ""}
+        </div>;
+    }
+
+    @computed get solidStk() { return this.selectedDoc?.color && (!this.selectedDoc?.strokeDash || this.selectedDoc?.strokeDash === "0") ? true : false; }
+    @computed get dashdStk() { return this.selectedDoc?.strokeDash || ""; }
+    @computed get unStrokd() { return this.selectedDoc?.color ? true : false; }
+    @computed get widthStk() { return this.getField("strokeWidth") || "1"; }
+    @computed get markHead() { return this.getField("strokeStartMarker") || ""; }
+    @computed get markTail() { return this.getField("strokeEndMarker") || ""; }
+    set solidStk(value) { this.dashdStk = ""; this.unStrokd = !value; }
+    set dashdStk(value) {
+        value && (this._lastDash = value) && (this.unStrokd = false);
+        this.selectedDoc && (this.selectedDoc.strokeDash = value ? this._lastDash : undefined);
+    }
+    set widthStk(value) { this.selectedDoc && (this.selectedDoc.strokeWidth = Number(value)); }
+    set unStrokd(value) { this.colorStk = value ? "" : this._lastLine; }
+    set markHead(value) { this.selectedDoc && (this.selectedDoc.strokeStartMarker = value); }
+    set markTail(value) { this.selectedDoc && (this.selectedDoc.strokeEndMarker = value); }
+
+
+    @computed get stkInput() { return this.regInput("stk", this.widthStk, (val: string) => this.widthStk = val); }
+
+
+    regInput = (key: string, value: any, setter: (val: string) => {}) => {
+        return <div className="inputBox">
+            <input className="inputBox-input"
+                type="text" value={value}
+                onChange={e => setter(e.target.value)} />
+            <div className="inputBox-button">
+                <div className="inputBox-button-up" key="up2"
+                    onPointerDown={undoBatch(action(() => this.upDownButtons("up", key)))} >
+                    <FontAwesomeIcon icon="caret-up" color="white" size="sm" />
+                </div>
+                <div className="inputbox-Button-down" key="down2"
+                    onPointerDown={undoBatch(action(() => this.upDownButtons("down", key)))} >
+                    <FontAwesomeIcon icon="caret-down" color="white" size="sm" />
+                </div>
+            </div>
+        </div>;
+    }
+
+    @computed get widthAndDash() {
+        return <div className="widthAndDash">
+            <div className="width">
+                <div className="width-top">
+                    <div className="width-title">Width:</div>
+                    <div className="width-input">{this.stkInput}</div>
+                </div>
+                <input className="width-range" type="range"
+                    defaultValue={Number(this.widthStk)} min={1} max={100}
+                    onChange={undoBatch(action((e) => this.widthStk = e.target.value))} />
+            </div>
+
+            <div className="arrows">
+                <div className="arrows-head">
+                    <div className="arrows-head-title" >Arrow Head: </div>
+                    <input key="markHead" className="arrows-head-input" type="checkbox"
+                        checked={this.markHead !== ""}
+                        onChange={undoBatch(action(() => this.markHead = this.markHead ? "" : "arrow"))} />
+                </div>
+                <div className="arrows-tail">
+                    <div className="arrows-tail-title" >Arrow End: </div>
+                    <input key="markTail" className="arrows-tail-input" type="checkbox"
+                        checked={this.markTail !== ""}
+                        onChange={undoBatch(action(() => this.markTail = this.markTail ? "" : "arrow"))} />
+                </div>
+            </div>
+            <div className="dashed">
+                <div className="dashed-title">Dash:</div>
+                <input key="markHead" className="dashed-input"
+                    type="checkbox" checked={this.dashdStk === "2"}
+                    onChange={this.changeDash} />
+            </div>
+        </div>;
+    }
+
+    @undoBatch @action
+    changeDash = () => {
+        const dash = this.dashdStk;
+        if (dash === "2") {
+            this.dashdStk = "0";
+        } else {
+            this.dashdStk = "2";
+        }
+    }
+
+    @computed get appearanceEditor() {
+        return <div className="appearance-editor">
+            {this.widthAndDash}
+            {this.strokeAndFill}
+        </div>;
+    }
+
+    @computed get transformEditor() {
+        return <div className="transform-editor">
+            {this.controlPointsButton}
+            {this.hgtInput}
+            {this.XpsInput}
+            {this.rotInput}
+        </div>;
+    }
+
+    render() {
+
+        if (!this.selectedDoc) {
+            return <div className="propertiesView" style={{ width: this.props.width }}>
+                <div className="propertiesView-title" style={{ width: this.props.width, paddingLeft: 6 }}>
+                    No Document Selected
+            </div> </div>;
+        }
+
+        const novice = Doc.UserDoc().noviceMode;
+
+        return <div className="propertiesView" style={{ width: this.props.width }} >
+            <div className="propertiesView-title" style={{ width: this.props.width }}>
+                Properties
+                <div className="propertiesView-title-icon" onPointerDown={this.props.onDown}>
+                    <FontAwesomeIcon icon="times" color="black" size="sm" />
+                </div>
+            </div>
+            <div className="propertiesView-name">
+                {this.editableTitle}
+            </div>
+            <div className="propertiesView-settings">
+                <div className="propertiesView-settings-title"
+                    onPointerDown={() => runInAction(() => { this.openActions = !this.openActions; })}
+                    style={{ backgroundColor: this.openActions ? "black" : "" }}>
+                    Actions
+                    <div className="propertiesView-settings-title-icon">
+                        <FontAwesomeIcon icon={this.openActions ? "caret-down" : "caret-right"} size="lg" color="white" />
+                    </div>
+                </div>
+                {this.openActions ? <div className="propertiesView-settings-content">
+                    <PropertiesButtons />
+                </div> : null}
+            </div>
+            <div className="propertiesView-sharing">
+                <div className="propertiesView-sharing-title"
+                    onPointerDown={() => runInAction(() => { this.openSharing = !this.openSharing; })}
+                    style={{ backgroundColor: this.openSharing ? "black" : "" }}>
+                    Sharing {"&"} Permissions
+                    <div className="propertiesView-sharing-title-icon">
+                        <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="white" />
+                    </div>
+                </div>
+                {this.openSharing ? <div className="propertiesView-sharing-content">
+                    {this.sharingTable}
+                </div> : null}
+            </div>
+
+
+
+
+            {this.isInk ? <div className="propertiesView-appearance">
+                <div className="propertiesView-appearance-title"
+                    onPointerDown={() => runInAction(() => { this.openAppearance = !this.openAppearance; })}
+                    style={{ backgroundColor: this.openAppearance ? "black" : "" }}>
+                    Appearance
+                    <div className="propertiesView-appearance-title-icon">
+                        <FontAwesomeIcon icon={this.openAppearance ? "caret-down" : "caret-right"} size="lg" color="white" />
+                    </div>
+                </div>
+                {this.openAppearance ? <div className="propertiesView-appearance-content">
+                    {this.appearanceEditor}
+                </div> : null}
+            </div> : null}
+
+            {this.isInk ? <div className="propertiesView-transform">
+                <div className="propertiesView-transform-title"
+                    onPointerDown={() => runInAction(() => { this.openTransform = !this.openTransform; })}
+                    style={{ backgroundColor: this.openTransform ? "black" : "" }}>
+                    Transform
+                    <div className="propertiesView-transform-title-icon">
+                        <FontAwesomeIcon icon={this.openTransform ? "caret-down" : "caret-right"} size="lg" color="white" />
+                    </div>
+                </div>
+                {this.openTransform ? <div className="propertiesView-transform-content">
+                    {this.transformEditor}
+                </div> : null}
+            </div> : null}
+
+
+
+
+
+            <div className="propertiesView-fields">
+                <div className="propertiesView-fields-title"
+                    onPointerDown={() => runInAction(() => { this.openFields = !this.openFields; })}
+                    style={{ backgroundColor: this.openFields ? "black" : "" }}>
+                    <div className="propertiesView-fields-title-name">
+                        Fields {"&"} Tags
+                        <div className="propertiesView-fields-title-icon">
+                            <FontAwesomeIcon icon={this.openFields ? "caret-down" : "caret-right"} size="lg" color="white" />
+                        </div>
+                    </div>
+                </div>
+                {!novice && this.openFields ? <div className="propertiesView-fields-checkbox">
+                    {this.fieldsCheckbox}
+                    <div className="propertiesView-fields-checkbox-text">Layout</div>
+                </div> : null}
+                {this.openFields ?
+                    <div className="propertiesView-fields-content">
+                        {novice ? this.noviceFields : this.expandedField}
+                    </div> : null}
+            </div>
+            <div className="propertiesView-layout">
+                <div className="propertiesView-layout-title"
+                    onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}
+                    style={{ backgroundColor: this.openLayout ? "black" : "" }}>
+                    Layout
+                    <div className="propertiesView-layout-title-icon"
+                        onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}>
+                        <FontAwesomeIcon icon={this.openLayout ? "caret-down" : "caret-right"} size="lg" color="white" />
+                    </div>
+                </div>
+                {this.openLayout ? <div className="propertiesView-layout-content">{this.layoutPreview}</div> : null}
+            </div>
+        </div>;
+    }
+} 
\ No newline at end of file
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index d1c839c3b..0aabf5319 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -182,7 +182,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
         switch (this.props.destinationDoc.type) {
             case DocumentType.IMG: destinationIcon = "image"; break;
             case DocumentType.COMPARISON: destinationIcon = "columns"; break;
-            case DocumentType.RTF: destinationIcon = "font"; break;
+            case DocumentType.RTF: destinationIcon = "sticky-note"; break;
             case DocumentType.COL: destinationIcon = "folder"; break;
             case DocumentType.WEB: destinationIcon = "globe-asia"; break;
             case DocumentType.SCREENSHOT: destinationIcon = "photo-video"; break;
@@ -196,6 +196,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
             case DocumentType.DOCHOLDER: destinationIcon = "expand"; break;
             case DocumentType.VID: destinationIcon = "video"; break;
             case DocumentType.INK: destinationIcon = "pen-nib"; break;
+            case DocumentType.PDF: destinationIcon = "file"; break;
             default: destinationIcon = "question"; break;
         }
 
diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx
index 6081def5d..f7e253f42 100644
--- a/src/client/views/nodes/ContentFittingDocumentView.tsx
+++ b/src/client/views/nodes/ContentFittingDocumentView.tsx
@@ -78,6 +78,9 @@ export class ContentFittingDocumentView extends React.Component<DocumentViewProp
 
     render() {
         TraceMobx();
+        if (this.props.Document.title === "Archive") {
+            console.log("");
+        }
         return (<div className="contentFittingDocumentView" style={{
             width: Math.abs(this.centeringYOffset) > 0.001 ? "auto" : this.props.PanelWidth(),
             height: Math.abs(this.centeringOffset) > 0.0001 ? "auto" : this.props.PanelHeight(),
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index e8173d103..e3f258b8d 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -18,6 +18,7 @@ import { DocHolderBox } from "./DocHolderBox";
 import { DocumentViewProps } from "./DocumentView";
 import "./DocumentView.scss";
 import { FontIconBox } from "./FontIconBox";
+import { MenuIconBox } from "./MenuIconBox";
 import { FieldView, FieldViewProps } from "./FieldView";
 import { FormattedTextBox } from "./formattedText/FormattedTextBox";
 import { ImageBox } from "./ImageBox";
@@ -189,7 +190,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
                 blacklistedAttrs={[]}
                 renderInWrapper={false}
                 components={{
-                    FormattedTextBox, ImageBox, DirectoryImportBox, FontIconBox, LabelBox, SliderBox, FieldView,
+                    FormattedTextBox, ImageBox, DirectoryImportBox, FontIconBox, MenuIconBox, LabelBox, SliderBox, FieldView,
                     CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValueBox,
                     PDFBox, VideoBox, AudioBox, PresBox, YoutubeBox, PresElementBox, QueryBox,
                     ColorBox, DashWebRTCVideo, LinkAnchorBox, InkingStroke, DocHolderBox, LinkBox, ScriptingBox,
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 3b91ac6b5..198a90225 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -198,8 +198,11 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
             // }))} 
             >
 
+                {/* {this.props.InMenu ? this.props.StartLink ? <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" /> :
+                    <FontAwesomeIcon className="documentdecorations-icon" icon="hand-paper" size="sm" /> : links.length} */}
+
                 {this.props.InMenu ? this.props.StartLink ? <FontAwesomeIcon className="documentdecorations-icon" icon="link" size="sm" /> :
-                    <FontAwesomeIcon className="documentdecorations-icon" icon="hand-paper" size="sm" /> : links.length}
+                    link : links.length}
 
             </div>
             {DocumentLinksButton.StartLink && this.props.InMenu && !!!this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View ? <div className={"documentLinksButton-endLink"}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index b3bfadf4f..22a2bb8fe 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -94,6 +94,8 @@ export interface DocumentViewProps {
     layoutKey?: string;
     radialMenu?: String[];
     display?: string;
+    relative?: boolean;
+    scriptContext?: any;
 }
 
 @observer
@@ -287,7 +289,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     }
 
     onClick = action((e: React.MouseEvent | React.PointerEvent) => {
-        if (!e.nativeEvent.cancelBubble && !this.Document.ignoreClick &&
+        if (!e.nativeEvent.cancelBubble && !this.Document.ignoreClick && this.props.renderDepth >= 0 &&
             (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) {
             let stopPropagate = true;
             let preventDefault = true;
@@ -319,10 +321,11 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 const func = () => this.onClickHandler.script.run({
                     this: this.layoutDoc,
                     self: this.rootDoc,
+                    scriptContext: this.props.scriptContext,
                     thisContainer: this.props.ContainingCollectionDoc,
                     shiftKey: e.shiftKey
                 }, console.log);
-                if (this.props.Document !== Doc.UserDoc()["dockedBtn-undo"] && this.props.Document !== Doc.UserDoc()["dockedBtn-redo"]) {
+                if (!Doc.AreProtosEqual(this.props.Document, Doc.UserDoc()["dockedBtn-undo"] as Doc) && !Doc.AreProtosEqual(this.props.Document, Doc.UserDoc()["dockedBtn-redo"] as Doc)) {
                     UndoManager.RunInBatch(func, "on click");
                 } else func();
             } else if (this.Document["onClick-rawScript"] && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes("ScriptingBox")) {// bcz: hack? don't edit a script if you're clicking on a scripting box itself
@@ -584,6 +587,18 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         }
     }
 
+
+    @undoBatch
+    noOnClick = (): void => {
+        this.Document.ignoreClick = false;
+        this.Document.isLinkButton = false;
+    }
+
+    @undoBatch
+    toggleDetail = (): void => {
+        this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`);
+    }
+
     @undoBatch @action
     drop = async (e: Event, de: DragManager.DropEvent) => {
         if (this.props.Document === Doc.UserDoc().activeWorkspace) {
@@ -660,6 +675,14 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         }
     }
 
+    @action
+    onCopy = () => {
+        const copy = Doc.MakeCopy(this.props.Document, true);
+        copy.x = NumCast(this.props.Document.x) + NumCast(this.props.Document._width);
+        copy.y = NumCast(this.props.Document.y) + 30;
+        this.props.addDocument?.(copy);
+    }
+
     @action
     onContextMenu = async (e: React.MouseEvent | Touch): Promise<void> => {
         // the touch onContextMenu is button 0, the pointer onContextMenu is button 2
@@ -704,14 +727,14 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         const existingOnClick = cm.findByDescription("OnClick...");
         const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : [];
         onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" });
-        onClicks.push({ description: "Toggle Detail", event: () => this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`), icon: "window-restore" });
+        onClicks.push({ description: "Toggle Detail", event: () => this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`), icon: "concierge-bell" });
         onClicks.push({ description: this.Document.ignoreClick ? "Select" : "Do Nothing", event: () => this.Document.ignoreClick = !this.Document.ignoreClick, icon: this.Document.ignoreClick ? "unlock" : "lock" });
-        onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link in Place", event: () => this.toggleFollowLink("inPlace", true, false), icon: "concierge-bell" });
-        !this.Document.isLinkButton && onClicks.push({ description: "Follow Link on Right", event: () => this.toggleFollowLink("onRight", false, false), icon: "concierge-bell" });
-        onClicks.push({ description: this.Document.isLinkButton || this.onClickHandler ? "Remove Click Behavior" : "Follow Link", event: () => this.toggleFollowLink(undefined, false, false), icon: "concierge-bell" });
-        onClicks.push({ description: (this.Document.isPushpin ? "Remove" : "Make") + " Pushpin", event: () => this.toggleFollowLink(undefined, false, true), icon: "snowflake" });
-        onClicks.push({ description: "Edit onClick Script", event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"), icon: "edit" });
-        !existingOnClick && cm.addItem({ description: "OnClick...", noexpand: true, addDivider: true, subitems: onClicks, icon: "hand-point-right" });
+        onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link in Place", event: () => this.toggleFollowLink("inPlace", true, false), icon: "link" });
+        !this.Document.isLinkButton && onClicks.push({ description: "Follow Link on Right", event: () => this.toggleFollowLink("onRight", false, false), icon: "link" });
+        onClicks.push({ description: this.Document.isLinkButton || this.onClickHandler ? "Remove Click Behavior" : "Follow Link", event: () => this.toggleFollowLink(undefined, false, false), icon: "link" });
+        onClicks.push({ description: (this.Document.isPushpin ? "Remove" : "Make") + " Pushpin", event: () => this.toggleFollowLink(undefined, false, true), icon: "map-pin" });
+        onClicks.push({ description: "Edit onClick Script", event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"), icon: "terminal" });
+        !existingOnClick && cm.addItem({ description: "OnClick...", noexpand: true, addDivider: true, subitems: onClicks, icon: "mouse-pointer" });
 
         const funcs: ContextMenuProps[] = [];
         if (this.layoutDoc.onDragStart) {
@@ -724,6 +747,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         const more = cm.findByDescription("More...");
         const moreItems = more && "subitems" in more ? more.subitems : [];
         moreItems.push({ description: "Download document", icon: "download", event: async () => Doc.Zip(this.props.Document) });
+        moreItems.push({ description: "Share", event: () => SharingManager.Instance.open(this), icon: "users" });
+        //moreItems.push({ description: this.Document.lockedPosition ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.Document.lockedPosition) ? "unlock" : "lock" });
+        moreItems.push({ description: "Create an Alias", event: () => this.onCopy(), icon: "copy" });
         if (!Doc.UserDoc().noviceMode) {
             moreItems.push({ description: "Make View of Metadata Field", event: () => Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.DataDoc), icon: "concierge-bell" });
             moreItems.push({ description: `${this.Document._chromeStatus !== "disabled" ? "Hide" : "Show"} Chrome`, event: () => this.Document._chromeStatus = (this.Document._chromeStatus !== "disabled" ? "disabled" : "enabled"), icon: "project-diagram" });
@@ -735,16 +761,18 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             }
             moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "fingerprint" });
         }
+        //GetEffectiveAcl(this.props.Document) === AclEdit && moreItems.push({ description: "Delete", event: this.deleteClicked, icon: "trash" });
+
         const effectiveAcl = GetEffectiveAcl(this.props.Document);
         (effectiveAcl === AclEdit || effectiveAcl === AclAdmin) && moreItems.push({ description: "Delete", event: this.deleteClicked, icon: "trash" });
-        moreItems.push({ description: "Share", event: () => SharingManager.Instance.open(this), icon: "external-link-alt" });
+
         !more && cm.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" });
         cm.moveAfter(cm.findByDescription("More...")!, cm.findByDescription("OnClick...")!);
 
         const help = cm.findByDescription("Help...");
         const helpItems: ContextMenuProps[] = help && "subitems" in help ? help.subitems : [];
+        !Doc.UserDoc().novice && helpItems.push({ description: "Show Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "onRight"), icon: "layer-group" });
         helpItems.push({ description: "Text Shortcuts Ctrl+/", event: () => this.props.addDocTab(Docs.Create.PdfDocument(Utils.prepend("/assets/cheat-sheet.pdf"), { _width: 300, _height: 300 }), "onRight"), icon: "keyboard" });
-        helpItems.push({ description: "Show Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "onRight"), icon: "layer-group" });
         helpItems.push({ description: "Print Document in Console", event: () => console.log(this.props.Document), icon: "hand-point-right" });
         cm.addItem({ description: "Help...", noexpand: true, subitems: helpItems, icon: "question" });
 
@@ -786,8 +814,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     childScaling = () => (this.layoutDoc._fitWidth ? this.props.PanelWidth() / this.nativeWidth : this.props.ContentScaling());
     @computed.struct get linkOffset() { return [-15, 0]; }
     @computed get contents() {
+        const pos = this.props.relative ? "relative " : "absolute";
         TraceMobx();
-        return (<div style={{ position: "absolute", width: "100%", height: "100%" }}>
+        return (<div style={{ width: "100%", height: "100%" }}>
             <DocumentContentsView key={1}
                 docFilters={this.props.docFilters}
                 ContainingCollectionView={this.props.ContainingCollectionView}
@@ -823,6 +852,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 ChromeHeight={this.chromeHeight}
                 isSelected={this.isSelected}
                 select={this.select}
+                scriptContext={this.props.scriptContext}
                 onClick={this.onClickFunc}
                 layoutKey={this.finalLayoutKey} />
             {this.layoutDoc.hideAllLinks ? (null) : this.allAnchors}
@@ -877,8 +907,12 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     }
     @computed get innards() {
         TraceMobx();
+        const pos = this.props.relative ? "relative" : undefined;
         if (this.props.treeViewDoc && !this.props.LayoutTemplateString?.includes("LinkAnchorBox")) {  // this happens when the document is a tree view label (but not an anchor dot)
-            return <div className="documentView-treeView" style={{ maxWidth: this.props.PanelWidth() || undefined }}>
+            return <div className="documentView-treeView" style={{
+                maxWidth: this.props.PanelWidth() || undefined,
+                position: pos
+            }}>
                 {StrCast(this.props.Document.title)}
                 {this.allAnchors}
             </div>;
@@ -1003,7 +1037,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                 background: finalColor,
                 opacity: finalOpacity,
                 fontFamily: StrCast(this.Document._fontFamily, "inherit"),
-                fontSize: Cast(this.Document._fontSize, "string", null)
+                fontSize: Cast(this.Document._fontSize, "string", null),
             }}>
             {this.onClickHandler && this.props.ContainingCollectionView?.props.Document._viewType === CollectionViewType.Time ? <>
                 {this.innards}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 5d5bc1d73..1b4151bd8 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -61,6 +61,7 @@ export interface FieldViewProps {
     color?: string;
     xMargin?: number;
     yMargin?: number;
+    scriptContext?: any;
 }
 
 @observer
diff --git a/src/client/views/nodes/FontIconBox.scss b/src/client/views/nodes/FontIconBox.scss
index 5b85d8b0b..69c835318 100644
--- a/src/client/views/nodes/FontIconBox.scss
+++ b/src/client/views/nodes/FontIconBox.scss
@@ -16,7 +16,7 @@
         position: absolute;
         text-align: center;
         font-size: 8px;
-        margin-top:4px;
+        //margin-top:4px;
         letter-spacing: normal;
         left: 0;
         overflow: hidden;
diff --git a/src/client/views/nodes/MenuIconBox.scss b/src/client/views/nodes/MenuIconBox.scss
new file mode 100644
index 000000000..1b72f5a8f
--- /dev/null
+++ b/src/client/views/nodes/MenuIconBox.scss
@@ -0,0 +1,49 @@
+.menuButton {
+    //padding: 7px;
+    padding-left: 7px;
+    width: 100%;
+    width: 60px;
+    height: 70px;
+
+    .menuButton-wrap {
+        width: 45px;
+        /* padding: 5px; */
+        touch-action: none;
+        background: black;
+        transform-origin: top left;
+        /* margin-bottom: 5px; */
+        margin-top: 5px;
+        margin-right: 25px;
+        border-radius: 8px;
+
+        &:hover {
+            background: rgb(61, 61, 61);
+            cursor: pointer;
+        }
+    }
+
+    .menuButton-label {
+        color: white;
+        margin-right: 4px;
+        border-radius: 8px;
+        width: 42px;
+        position: relative;
+        text-align: center;
+        font-size: 8px;
+        margin-top: 1px;
+        letter-spacing: normal;
+        padding: 3px;
+        background-color: inherit;
+    }
+
+    .menuButton-icon {
+        width: auto;
+        height: 35px;
+        padding: 5px;
+    }
+
+    svg {
+        width: 95% !important;
+        height: 95%;
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/nodes/MenuIconBox.tsx b/src/client/views/nodes/MenuIconBox.tsx
new file mode 100644
index 000000000..0aa7b327e
--- /dev/null
+++ b/src/client/views/nodes/MenuIconBox.tsx
@@ -0,0 +1,33 @@
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { observer } from 'mobx-react';
+import * as React from 'react';
+import { createSchema, makeInterface } from '../../../fields/Schema';
+import { StrCast } from '../../../fields/Types';
+import { DocComponent } from '../DocComponent';
+import { FieldView, FieldViewProps } from './FieldView';
+import './MenuIconBox.scss';
+const MenuIconSchema = createSchema({
+    icon: "string"
+});
+
+type MenuIconDocument = makeInterface<[typeof MenuIconSchema]>;
+const MenuIconDocument = makeInterface(MenuIconSchema);
+@observer
+export class MenuIconBox extends DocComponent<FieldViewProps, MenuIconDocument>(MenuIconDocument) {
+    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(MenuIconBox, fieldKey); }
+    _ref: React.RefObject<HTMLButtonElement> = React.createRef();
+
+    render() {
+
+        const color = this.props.backgroundColor?.(this.props.Document) === "lightgrey" ? "black" : "white";
+        const menuBTN = <div className="menuButton" style={{ backgroundColor: this.props.backgroundColor?.(this.props.Document) }}>
+            <div className="menuButton-wrap"
+                style={{ backgroundColor: this.props.backgroundColor?.(this.props.Document) }} >
+                <FontAwesomeIcon className="menuButton-icon" icon={StrCast(this.dataDoc.icon, "user") as any} color={color} size="lg" />
+                <div className="menuButton-label" style={{ color: color }}> {this.dataDoc.title} </div>
+            </div>
+        </div>;
+
+        return menuBTN;
+    }
+}
\ No newline at end of file
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index c04c6c409..97f223c02 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -32,6 +32,7 @@ import { conformsTo } from "lodash";
 import { translate } from "googleapis/build/src/apis/translate";
 import { DragManager, dropActionType } from "../../util/DragManager";
 import { actionAsync } from "mobx-utils";
+import { SelectionManager } from "../../util/SelectionManager";
 
 type PresBoxSchema = makeInterface<[typeof documentSchema]>;
 const PresBoxDocument = makeInterface(documentSchema);
@@ -260,7 +261,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
         const srcContext = await DocCastAsync(targetDoc.context);
         const presCollection = Cast(this.layoutDoc.presCollection, Doc, null);
-        const collectionDocView = presCollection ? DocumentManager.Instance.getDocumentView(presCollection) : undefined;
+        const collectionDocView = presCollection ? await DocumentManager.Instance.getDocumentView(presCollection) : undefined;
         if (this.itemIndex >= 0) {
             if (targetDoc) {
                 if (srcContext) this.layoutDoc.presCollection = srcContext;
@@ -496,6 +497,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
     selectElement = (doc: Doc) => {
         // this._selectedArray = [];
         this.gotoDocument(this.childDocs.indexOf(doc), NumCast(this.itemIndex));
+        const view = DocumentManager.Instance.getDocumentView(doc);
+        view && SelectionManager.SelectDoc(view, false);
         // this._selectedArray.push(this.childDocs[this.childDocs.indexOf(doc)]);
         // console.log(this._selectedArray);
     }
@@ -504,8 +507,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
     @action
     multiSelect = (doc: Doc, ref: HTMLElement) => {
         this._selectedArray.push(this.childDocs[this.childDocs.indexOf(doc)]);
-        const ele = ref.getElementsByClassName("stacking");
         this._eleArray.push(ref);
+        const view = DocumentManager.Instance.getDocumentView(doc);
+        view && SelectionManager.SelectDoc(view, true);
     }
 
     //Shift click
@@ -517,6 +521,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
             for (let i = Math.min(this.itemIndex, this.childDocs.indexOf(doc)); i <= Math.max(this.itemIndex, this.childDocs.indexOf(doc)); i++) {
                 this._selectedArray.push(this.childDocs[i]);
                 this._eleArray.push(ref);
+                const view = DocumentManager.Instance.getDocumentView(doc);
+                view && SelectionManager.SelectDoc(view, true);
             }
         }
     }
diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx
index 958a37568..8ae71c035 100644
--- a/src/client/views/nodes/formattedText/DashFieldView.tsx
+++ b/src/client/views/nodes/formattedText/DashFieldView.tsx
@@ -190,7 +190,7 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
             }
             list.map(c => c.heading).indexOf(this._fieldKey) === -1 && list.push(new SchemaHeaderField(this._fieldKey, "#f1efeb"));
             list.map(c => c.heading).indexOf("text") === -1 && list.push(new SchemaHeaderField("text", "#f1efeb"));
-            alias._pivotField = this._fieldKey;
+            alias._pivotField = this._fieldKey.startsWith("#") ? "#" : this._fieldKey;
             this.props.tbox.props.addDocTab(alias, "onRight");
         }
     }
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 627c6e363..fc65f34eb 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1267,7 +1267,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         this.doLinkOnDeselect();
 
         // move the richtextmenu offscreen
-        if (!RichTextMenu.Instance.Pinned) RichTextMenu.Instance.delayHide();
+        //if (!RichTextMenu.Instance.Pinned) RichTextMenu.Instance.delayHide();
     }
 
     _lastTimedMark: Mark | undefined = undefined;
@@ -1346,7 +1346,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
     @computed get sidebarColor() { return StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], "transparent")); }
     render() {
         TraceMobx();
-        const scale = this.props.ContentScaling() * NumCast(this.layoutDoc._viewScale, 1);
+        const scale = this.props.hideOnLeave ? 1 : this.props.ContentScaling() * NumCast(this.layoutDoc._viewScale, 1);
         const rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : "";
         const interactive = Doc.GetSelectedTool() === InkTool.None && !this.layoutDoc.isBackground;
         setTimeout(() => this._editorView && RichTextMenu.Instance.updateFromDash(this._editorView, undefined, this.props), this.props.isSelected() ? 10 : 0); // need to make sure that we update a text box that is selected after updating the one that was deselected
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index 7ccbfa051..f76707a79 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -77,7 +77,8 @@ export default class RichTextMenu extends AntimodeMenu {
         super(props);
         RichTextMenu.Instance = this;
         this._canFade = false;
-        this.Pinned = BoolCast(Doc.UserDoc()["menuRichText-pinned"]);
+        //this.Pinned = BoolCast(Doc.UserDoc()["menuRichText-pinned"]);
+        this.Pinned = true;
 
         this.fontSizeOptions = [
             { mark: schema.marks.pFontSize.create({ fontSize: 7 }), title: "Set font size", label: "7pt", command: this.changeFontSize },
@@ -529,7 +530,7 @@ export default class RichTextMenu extends AntimodeMenu {
 
     indentParagraph(state: EditorState<any>, dispatch: any) {
         var tr = state.tr;
-        let headin = false;
+        const heading = false;
         state.doc.nodesBetween(state.selection.from, state.selection.to, (node, pos, parent, index) => {
             if (node.type === schema.nodes.paragraph || node.type === schema.nodes.heading) {
                 const nodeval = node.attrs.indent ? Number(node.attrs.indent) : undefined;
@@ -539,7 +540,7 @@ export default class RichTextMenu extends AntimodeMenu {
             }
             return true;
         });
-        !headin && dispatch?.(tr);
+        !heading && dispatch?.(tr);
         return true;
     }
 
@@ -920,16 +921,22 @@ export default class RichTextMenu extends AntimodeMenu {
     render() {
         TraceMobx();
         const row1 = <div className="antimodeMenu-row" key="row 1" style={{ display: this.collapsed ? "none" : undefined }}>{[
-            !this.collapsed ? this.getDragger() : (null),
-            !this.Pinned ? (null) : <div key="frag1"> {[
-                this.createButton("bold", "Bold", this.boldActive, toggleMark(schema.marks.strong)),
-                this.createButton("italic", "Italic", this.italicsActive, toggleMark(schema.marks.em)),
-                this.createButton("underline", "Underline", this.underlineActive, toggleMark(schema.marks.underline)),
-                this.createButton("strikethrough", "Strikethrough", this.strikethroughActive, toggleMark(schema.marks.strikethrough)),
-                this.createButton("superscript", "Superscript", this.superscriptActive, toggleMark(schema.marks.superscript)),
-                this.createButton("subscript", "Subscript", this.subscriptActive, toggleMark(schema.marks.subscript)),
-                <div className="richTextMenu-divider" key="divider" />
-            ]}</div>,
+            //!this.collapsed ? this.getDragger() : (null),
+            // !this.Pinned ? (null) : <div key="frag1"> {[
+            //     this.createButton("bold", "Bold", this.boldActive, toggleMark(schema.marks.strong)),
+            //     this.createButton("italic", "Italic", this.italicsActive, toggleMark(schema.marks.em)),
+            //     this.createButton("underline", "Underline", this.underlineActive, toggleMark(schema.marks.underline)),
+            //     this.createButton("strikethrough", "Strikethrough", this.strikethroughActive, toggleMark(schema.marks.strikethrough)),
+            //     this.createButton("superscript", "Superscript", this.superscriptActive, toggleMark(schema.marks.superscript)),
+            //     this.createButton("subscript", "Subscript", this.subscriptActive, toggleMark(schema.marks.subscript)),
+            //     <div className="richTextMenu-divider" key="divider" />
+            // ]}</div>,
+            this.createButton("bold", "Bold", this.boldActive, toggleMark(schema.marks.strong)),
+            this.createButton("italic", "Italic", this.italicsActive, toggleMark(schema.marks.em)),
+            this.createButton("underline", "Underline", this.underlineActive, toggleMark(schema.marks.underline)),
+            this.createButton("strikethrough", "Strikethrough", this.strikethroughActive, toggleMark(schema.marks.strikethrough)),
+            this.createButton("superscript", "Superscript", this.superscriptActive, toggleMark(schema.marks.superscript)),
+            this.createButton("subscript", "Subscript", this.subscriptActive, toggleMark(schema.marks.subscript)),
             this.createColorButton(),
             this.createHighlighterButton(),
             this.createLinkButton(),
@@ -957,16 +964,16 @@ export default class RichTextMenu extends AntimodeMenu {
                 this.createButton("minus", "Horizontal Rule", undefined, this.insertHorizontalRule),
                 <div className="richTextMenu-divider" key="divider 5" />,]}
             </div>
-            <div key="collapser">
-                {/* <div key="collapser">
+            {/* <div key="collapser">
+                {<div key="collapser">
                     <button className="antimodeMenu-button" key="collapse menu" title="Collapse menu" onClick={this.toggleCollapse} style={{ backgroundColor: this.collapsed ? "#121212" : "", width: 25 }}>
                         <FontAwesomeIcon icon="chevron-left" size="lg" style={{ transitionProperty: "transform", transitionDuration: "0.3s", transform: `rotate(${this.collapsed ? 180 : 0}deg)` }} />
                     </button>
-                </div> */}
+                </div> }
                 <button className="antimodeMenu-button" key="pin menu" title="Pin menu" onClick={this.toggleMenuPin} style={{ backgroundColor: this.Pinned ? "#121212" : "", display: this.collapsed ? "none" : undefined }}>
                     <FontAwesomeIcon icon="thumbtack" size="lg" style={{ transitionProperty: "transform", transitionDuration: "0.1s", transform: `rotate(${this.Pinned ? 45 : 0}deg)` }} />
                 </button>
-            </div>
+            </div> */}
         </div>;
 
         return (
diff --git a/src/client/views/nodes/formattedText/nodes_rts.ts b/src/client/views/nodes/formattedText/nodes_rts.ts
index 0eca6d753..1616500f6 100644
--- a/src/client/views/nodes/formattedText/nodes_rts.ts
+++ b/src/client/views/nodes/formattedText/nodes_rts.ts
@@ -79,14 +79,14 @@ export const nodes: { [index: string]: NodeSpec } = {
         { tag: "h5", attrs: { level: 5 } },
         { tag: "h6", attrs: { level: 6 } }],
         toDOM(node) {
-            var dom = toParagraphDOM(node) as any;
-            var level = node.attrs.level || 1;
+            const dom = toParagraphDOM(node) as any;
+            const level = node.attrs.level || 1;
             dom[0] = 'h' + level;
             return dom;
         },
         getAttrs(dom: any) {
-            var attrs = getParagraphNodeAttrs(dom) as any;
-            var level = Number(dom.nodeName.substring(1)) || 1;
+            const attrs = getParagraphNodeAttrs(dom) as any;
+            const level = Number(dom.nodeName.substring(1)) || 1;
             attrs.level = level;
             return attrs;
         }
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 43e74ff61..85fc63074 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -528,10 +528,10 @@ export namespace Doc {
             const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key]));
             const field = ProxyField.WithoutProxy(() => doc[key]);
             const copyObjectField = async (field: ObjectField) => {
-                const list = await Cast(doc[key], listSpec(Doc));
+                const list = Cast(doc[key], listSpec(Doc));
                 const docs = list && (await DocListCastAsync(list))?.filter(d => d instanceof Doc);
                 if (docs !== undefined && docs.length) {
-                    const clones = await Promise.all(docs.map(async d => await Doc.makeClone(d as Doc, cloneMap, rtfs, exclusions, dontCreate)));
+                    const clones = await Promise.all(docs.map(async d => Doc.makeClone(d, cloneMap, rtfs, exclusions, dontCreate)));
                     !dontCreate && assignKey(new List<Doc>(clones));
                 } else if (doc[key] instanceof Doc) {
                     assignKey(key.includes("layout[") ? undefined : key.startsWith("layout") ? doc[key] as Doc : await Doc.makeClone(doc[key] as Doc, cloneMap, rtfs, exclusions, dontCreate)); // reference documents except copy documents that are expanded teplate fields 
@@ -625,7 +625,7 @@ export namespace Doc {
         Array.from(map.entries()).forEach(f => docs[f[0]] = f[1]);
         const docString = JSON.stringify({ id: doc[Id], docs }, replacer);
 
-        var zip = new JSZip();
+        const zip = new JSZip();
 
         zip.file(doc.title + ".json", docString);
 
diff --git a/src/server/ActionUtilities.ts b/src/server/ActionUtilities.ts
index 60f66c878..fd9bc0c83 100644
--- a/src/server/ActionUtilities.ts
+++ b/src/server/ActionUtilities.ts
@@ -1,11 +1,11 @@
-import { readFile, writeFile, exists, mkdir, unlink, createWriteStream } from 'fs';
-import { ExecOptions } from 'shelljs';
 import { exec } from 'child_process';
-import * as path from 'path';
-import * as rimraf from "rimraf";
-import { yellow, Color } from 'colors';
+import { Color, yellow } from 'colors';
+import { createWriteStream, exists, mkdir, readFile, unlink, writeFile } from 'fs';
 import * as nodemailer from "nodemailer";
 import { MailOptions } from "nodemailer/lib/json-transport";
+import * as path from 'path';
+import * as rimraf from "rimraf";
+import { ExecOptions } from 'shelljs';
 import Mail = require('nodemailer/lib/mailer');
 
 const projectRoot = path.resolve(__dirname, "../../");
diff --git a/src/server/ApiManagers/UtilManager.ts b/src/server/ApiManagers/UtilManager.ts
index e2cd88726..e657866ce 100644
--- a/src/server/ApiManagers/UtilManager.ts
+++ b/src/server/ApiManagers/UtilManager.ts
@@ -6,7 +6,6 @@ import { exec } from 'child_process';
 
 // const recommender = new Recommender();
 // recommender.testModel();
-import executeImport from "../../scraping/buxton/final/BuxtonImporter";
 
 export default class UtilManager extends ApiManager {
 
diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts
index 2bf4c1956..890fb6f6d 100644
--- a/src/server/DashUploadUtils.ts
+++ b/src/server/DashUploadUtils.ts
@@ -1,23 +1,22 @@
-import { unlinkSync, createWriteStream, readFileSync, rename, writeFile, existsSync } from 'fs';
-import { Utils } from '../Utils';
-import * as path from 'path';
-import * as sharp from 'sharp';
-import request = require('request-promise');
+import { red } from 'colors';
 import { ExifImage } from 'exif';
-import { Opt } from '../fields/Doc';
-import { AcceptibleMedia, Upload } from './SharedMediaTypes';
-import { filesDirectory, publicDirectory } from '.';
 import { File } from 'formidable';
+import { createWriteStream, existsSync, readFileSync, rename, unlinkSync, writeFile } from 'fs';
+import * as path from 'path';
 import { basename } from "path";
-import { createIfNotExists } from './ActionUtilities';
+import * as sharp from 'sharp';
+import { Stream } from 'stream';
+import { filesDirectory, publicDirectory } from '.';
+import { Opt } from '../fields/Doc';
 import { ParsedPDF } from "../server/PdfTypes";
+import { Utils } from '../Utils';
+import { createIfNotExists } from './ActionUtilities';
+import { clientPathToFile, Directory, pathToDirectory, serverPathToFile } from './ApiManagers/UploadManager';
+import { resolvedServerUrl } from "./server_Initialization";
+import { AcceptibleMedia, Upload } from './SharedMediaTypes';
+import request = require('request-promise');
 const parse = require('pdf-parse');
-import { Directory, serverPathToFile, clientPathToFile, pathToDirectory } from './ApiManagers/UploadManager';
-import { red } from 'colors';
-import { Stream } from 'stream';
-import { resolvedPorts } from './server_Initialization';
 const requestImageSize = require("../client/util/request-image-size");
-import { resolvedServerUrl } from "./server_Initialization";
 
 export enum SizeSuffix {
     Small = "_s",
diff --git a/src/server/GarbageCollector.ts b/src/server/GarbageCollector.ts
index 24745cbb4..a9a3b0481 100644
--- a/src/server/GarbageCollector.ts
+++ b/src/server/GarbageCollector.ts
@@ -1,9 +1,9 @@
-import { Database } from './database';
-
-import * as path from 'path';
 import * as fs from 'fs';
+import * as path from 'path';
+import { Database } from './database';
 import { Search } from './Search';
 
+
 function addDoc(doc: any, ids: string[], files: { [name: string]: string[] }) {
     for (const key in doc) {
         if (!doc.hasOwnProperty(key)) {
diff --git a/src/server/MemoryDatabase.ts b/src/server/MemoryDatabase.ts
index 1f1d702d9..7f477327e 100644
--- a/src/server/MemoryDatabase.ts
+++ b/src/server/MemoryDatabase.ts
@@ -1,6 +1,7 @@
-import { IDatabase, DocumentsCollection } from './IDatabase';
-import { Transferable } from './Message';
+import { DH_CHECK_P_NOT_SAFE_PRIME } from 'constants';
 import * as mongodb from 'mongodb';
+import { DocumentsCollection, IDatabase } from './IDatabase';
+import { Transferable } from './Message';
 
 export class MemoryDatabase implements IDatabase {
 
diff --git a/src/server/Message.ts b/src/server/Message.ts
index ff0381fd3..59b24cd82 100644
--- a/src/server/Message.ts
+++ b/src/server/Message.ts
@@ -1,6 +1,6 @@
-import { Utils } from "../Utils";
 import { Point } from "../pen-gestures/ndollar";
 import { AnalysisResult, ImportResults } from "../scraping/buxton/final/BuxtonImporter";
+import { Utils } from "../Utils";
 
 export class Message<T> {
     private _name: string;
diff --git a/src/server/ProcessFactory.ts b/src/server/ProcessFactory.ts
index acb8b3a99..63682368f 100644
--- a/src/server/ProcessFactory.ts
+++ b/src/server/ProcessFactory.ts
@@ -1,8 +1,8 @@
-import { existsSync, mkdirSync } from "fs";
-import { pathFromRoot, fileDescriptorFromStream } from './ActionUtilities';
-import rimraf = require("rimraf");
 import { ChildProcess, spawn, StdioOptions } from "child_process";
+import { existsSync, mkdirSync } from "fs";
 import { Stream } from "stream";
+import { fileDescriptorFromStream, pathFromRoot } from './ActionUtilities';
+import rimraf = require("rimraf");
 
 export namespace ProcessFactory {
 
diff --git a/src/server/Recommender.ts b/src/server/Recommender.ts
deleted file mode 100644
index 935ec3871..000000000
--- a/src/server/Recommender.ts
+++ /dev/null
@@ -1,133 +0,0 @@
-// //import { Doc } from "../fields/Doc";
-// //import { StrCast } from "../fields/Types";
-// //import { List } from "../fields/List";
-// //import { CognitiveServices } from "../client/cognitive_services/CognitiveServices";
-
-// // var w2v = require('word2vec');
-// var assert = require('assert');
-// var arxivapi = require('arxiv-api-node');
-// import requestPromise = require("request-promise");
-// import * as use from '@tensorflow-models/universal-sentence-encoder';
-// import { Tensor } from "@tensorflow/tfjs-core/dist/tensor";
-// require('@tensorflow/tfjs-node');
-
-// //http://gnuwin32.sourceforge.net/packages/make.htm
-
-// export class Recommender {
-
-//     private _model: any;
-//     static Instance: Recommender;
-//     private dimension: number = 0;
-//     private choice: string = ""; // Tensorflow or Word2Vec
-
-//     constructor() {
-//         Recommender.Instance = this;
-//     }
-
-//     /***
-//      * Loads pre-trained model from TF
-//      */
-
-//     public async loadTFModel() {
-//         let self = this;
-//         return new Promise(res => {
-//             use.load().then(model => {
-//                 self.choice = "TF";
-//                 self._model = model;
-//                 self.dimension = 512;
-//                 res(model);
-//             });
-//         }
-
-//         );
-//     }
-
-//     /***
-//      * Loads pre-trained model from word2vec
-//      */
-
-//     // private loadModel(): Promise<any> {
-//     //     let self = this;
-//     //     return new Promise(res => {
-//     //         w2v.loadModel("./node_modules/word2vec/examples/fixtures/vectors.txt", function (err: any, model: any) {
-//     //             self.choice = "WV";
-//     //             self._model = model;
-//     //             self.dimension = model.size;
-//     //             res(model);
-//     //         });
-//     //     });
-//     // }
-
-//     /***
-//      * Testing
-//      */
-
-//     public async testModel() {
-//         if (!this._model) {
-//             await this.loadTFModel();
-//         }
-//         if (this._model) {
-//             if (this.choice === "WV") {
-//                 let similarity = this._model.similarity('father', 'mother');
-//             }
-//             else if (this.choice === "TF") {
-//                 const model = this._model as use.UniversalSentenceEncoder;
-//                 // Embed an array of sentences.
-//                 const sentences = [
-//                     'Hello.',
-//                     'How are you?'
-//                 ];
-//                 const embeddings = await this.vectorize(sentences);
-//                 if (embeddings) embeddings.print(true /*verbose*/);
-//                 // model.embed(sentences).then(embeddings => {
-//                 //     // `embeddings` is a 2D tensor consisting of the 512-dimensional embeddings for each sentence.
-//                 //     // So in this example `embeddings` has the shape [2, 512].
-//                 //     embeddings.print(true /* verbose */);
-//                 // });
-//             }
-//         }
-//         else {
-//             console.log("model not found :(");
-//         }
-//     }
-
-//     /***
-//      * Uses model to convert words to vectors
-//      */
-
-//     public async vectorize(text: string[]): Promise<Tensor | undefined> {
-//         if (!this._model) {
-//             await this.loadTFModel();
-//         }
-//         if (this._model) {
-//             if (this.choice === "WV") {
-//                 let word_vecs = this._model.getVectors(text);
-//                 return word_vecs;
-//             }
-//             else if (this.choice === "TF") {
-//                 const model = this._model as use.UniversalSentenceEncoder;
-//                 return new Promise<Tensor>(res => {
-//                     model.embed(text).then(embeddings => {
-//                         res(embeddings);
-//                     });
-//                 });
-
-//             }
-//         }
-//     }
-
-//     // public async trainModel() {
-//     //     w2v.word2vec("./node_modules/word2vec/examples/eng_news-typical_2016_1M-sentences.txt", './node_modules/word2vec/examples/my_phrases.txt', {
-//     //         cbow: 1,
-//     //         size: 200,
-//     //         window: 8,
-//     //         negative: 25,
-//     //         hs: 0,
-//     //         sample: 1e-4,
-//     //         threads: 20,
-//     //         iter: 200,
-//     //         minCount: 2
-//     //     });
-//     // }
-
-// }
diff --git a/src/server/RouteManager.ts b/src/server/RouteManager.ts
index 1a2340afc..78b75d6be 100644
--- a/src/server/RouteManager.ts
+++ b/src/server/RouteManager.ts
@@ -1,8 +1,8 @@
-import RouteSubscriber from "./RouteSubscriber";
-import { DashUserModel } from "./authentication/DashUserModel";
-import { Request, Response, Express } from 'express';
-import { cyan, red, green } from 'colors';
+import { cyan, green, red } from 'colors';
+import { Express, Request, Response } from 'express';
 import { AdminPriviliges } from ".";
+import { DashUserModel } from "./authentication/DashUserModel";
+import RouteSubscriber from "./RouteSubscriber";
 
 export enum Method {
     GET,
diff --git a/src/server/Search.ts b/src/server/Search.ts
index 21064e520..decd1f5b1 100644
--- a/src/server/Search.ts
+++ b/src/server/Search.ts
@@ -1,5 +1,5 @@
-import * as rp from 'request-promise';
 import { red } from 'colors';
+import * as rp from 'request-promise';
 
 const pathTo = (relative: string) => `http://localhost:8983/solr/dash/${relative}`;
 
diff --git a/src/server/database.ts b/src/server/database.ts
index 2372cbcf2..b7aa77f5d 100644
--- a/src/server/database.ts
+++ b/src/server/database.ts
@@ -1,11 +1,11 @@
 import * as mongodb from 'mongodb';
-import { Transferable } from './Message';
+import * as mongoose from 'mongoose';
 import { Opt } from '../fields/Doc';
-import { Utils, emptyFunction } from '../Utils';
+import { emptyFunction, Utils } from '../Utils';
 import { GoogleApiServerUtils } from './apis/google/GoogleApiServerUtils';
-import { IDatabase, DocumentsCollection } from './IDatabase';
+import { DocumentsCollection, IDatabase } from './IDatabase';
 import { MemoryDatabase } from './MemoryDatabase';
-import * as mongoose from 'mongoose';
+import { Transferable } from './Message';
 import { Upload } from './SharedMediaTypes';
 
 export namespace Database {
diff --git a/src/server/downsize.ts b/src/server/downsize.ts
index 5cd709fa3..382994e2d 100644
--- a/src/server/downsize.ts
+++ b/src/server/downsize.ts
@@ -1,5 +1,5 @@
-import * as sharp from 'sharp';
 import * as fs from 'fs';
+import * as sharp from 'sharp';
 
 const folder = "./src/server/public/files/";
 const pngTypes = ["png", "PNG"];
diff --git a/src/server/index.ts b/src/server/index.ts
index 9af4b00bc..9185e3c5e 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -1,29 +1,29 @@
 require('dotenv').config();
-import { GoogleApiServerUtils } from "./apis/google/GoogleApiServerUtils";
+import { yellow } from "colors";
 import * as mobileDetect from 'mobile-detect';
 import * as path from 'path';
-import { Database } from './database';
-import { DashUploadUtils } from './DashUploadUtils';
-import RouteSubscriber from './RouteSubscriber';
-import initializeServer, { resolvedPorts } from './server_Initialization';
-import RouteManager, { Method, _success, _permission_denied, _error, _invalid, PublicHandler } from './RouteManager';
 import * as qs from 'query-string';
-import UtilManager from './ApiManagers/UtilManager';
-import { SearchManager } from './ApiManagers/SearchManager';
-import UserManager from './ApiManagers/UserManager';
-import DownloadManager from './ApiManagers/DownloadManager';
-import { GoogleCredentialsLoader, SSL } from './apis/google/CredentialsLoader';
-import DeleteManager from "./ApiManagers/DeleteManager";
-import PDFManager from "./ApiManagers/PDFManager";
-import UploadManager from "./ApiManagers/UploadManager";
 import { log_execution } from "./ActionUtilities";
+import DeleteManager from "./ApiManagers/DeleteManager";
+import DownloadManager from './ApiManagers/DownloadManager';
 import GeneralGoogleManager from "./ApiManagers/GeneralGoogleManager";
-import HypothesisManager from "./ApiManagers/HypothesisManager";
 import GooglePhotosManager from "./ApiManagers/GooglePhotosManager";
-import { Logger } from "./ProcessFactory";
-import { yellow } from "colors";
+import HypothesisManager from "./ApiManagers/HypothesisManager";
+import PDFManager from "./ApiManagers/PDFManager";
+import { SearchManager } from './ApiManagers/SearchManager';
 import SessionManager from "./ApiManagers/SessionManager";
+import UploadManager from "./ApiManagers/UploadManager";
+import UserManager from './ApiManagers/UserManager';
+import UtilManager from './ApiManagers/UtilManager';
+import { GoogleCredentialsLoader, SSL } from './apis/google/CredentialsLoader';
+import { GoogleApiServerUtils } from "./apis/google/GoogleApiServerUtils";
 import { AppliedSessionAgent } from "./DashSession/Session/agents/applied_session_agent";
+import { DashUploadUtils } from './DashUploadUtils';
+import { Database } from './database';
+import { Logger } from "./ProcessFactory";
+import RouteManager, { Method, PublicHandler } from './RouteManager';
+import RouteSubscriber from './RouteSubscriber';
+import initializeServer, { resolvedPorts } from './server_Initialization';
 
 export const AdminPriviliges: Map<string, boolean> = new Map();
 export const onWindows = process.platform === "win32";
diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts
index 744d4547b..e40f2b8e5 100644
--- a/src/server/server_Initialization.ts
+++ b/src/server/server_Initialization.ts
@@ -1,31 +1,31 @@
+import * as bodyParser from 'body-parser';
+import { blue, yellow } from 'colors';
+import * as cookieParser from 'cookie-parser';
+import * as cors from "cors";
 import * as express from 'express';
-import * as expressValidator from 'express-validator';
 import * as session from 'express-session';
+import * as expressValidator from 'express-validator';
+import * as fs from 'fs';
+import { Server as HttpServer } from "http";
+import { createServer, Server as HttpsServer } from "https";
 import * as passport from 'passport';
-import * as bodyParser from 'body-parser';
-import * as cookieParser from 'cookie-parser';
-import expressFlash = require('express-flash');
-import flash = require('connect-flash');
-import { Database } from './database';
-import { getForgot, getLogin, getLogout, getReset, getSignup, postForgot, postLogin, postReset, postSignup } from './authentication/AuthenticationManager';
-const MongoStore = require('connect-mongo')(session);
-import RouteManager from './RouteManager';
-import { WebSocket } from './websocket';
+import * as request from 'request';
 import * as webpack from 'webpack';
-const config = require('../../webpack.config');
-const compiler = webpack(config);
 import * as wdm from 'webpack-dev-middleware';
 import * as whm from 'webpack-hot-middleware';
-import * as fs from 'fs';
-import * as request from 'request';
-import RouteSubscriber from './RouteSubscriber';
 import { publicDirectory } from '.';
 import { logPort } from './ActionUtilities';
-import { blue, yellow } from 'colors';
-import * as cors from "cors";
-import { createServer, Server as HttpsServer } from "https";
-import { Server as HttpServer } from "http";
 import { SSL } from './apis/google/CredentialsLoader';
+import { getForgot, getLogin, getLogout, getReset, getSignup, postForgot, postLogin, postReset, postSignup } from './authentication/AuthenticationManager';
+import { Database } from './database';
+import RouteManager from './RouteManager';
+import RouteSubscriber from './RouteSubscriber';
+import { WebSocket } from './websocket';
+import expressFlash = require('express-flash');
+import flash = require('connect-flash');
+const MongoStore = require('connect-mongo')(session);
+const config = require('../../webpack.config');
+const compiler = webpack(config);
 
 /* RouteSetter is a wrapper around the server that prevents the server
    from being exposed. */
diff --git a/src/server/websocket.ts b/src/server/websocket.ts
index f63a35e43..d5f89a750 100644
--- a/src/server/websocket.ts
+++ b/src/server/websocket.ts
@@ -1,21 +1,20 @@
-import * as fs from 'fs';
-import { logPort } from './ActionUtilities';
-import { Utils } from "../Utils";
-import { MessageStore, Transferable, Types, Diff, YoutubeQueryInput, YoutubeQueryTypes, GestureContent, MobileInkOverlayContent, UpdateMobileInkOverlayPositionContent, MobileDocumentUploadContent, RoomMessage } from "./Message";
-import { Client } from "./Client";
-import { Socket } from "socket.io";
-import { Database } from "./database";
-import { Search } from "./Search";
-import * as sio from 'socket.io';
-import YoutubeApi from "./apis/youtube/youtubeApiSample";
-import { GoogleCredentialsLoader, SSL } from "./apis/google/CredentialsLoader";
-import { timeMap } from "./ApiManagers/UserManager";
 import { green } from "colors";
+import * as express from "express";
+import { createServer, Server } from "https";
 import { networkInterfaces } from "os";
+import * as sio from 'socket.io';
+import { Socket } from "socket.io";
 import executeImport from "../scraping/buxton/final/BuxtonImporter";
+import { Utils } from "../Utils";
+import { logPort } from './ActionUtilities';
+import { timeMap } from "./ApiManagers/UserManager";
+import { GoogleCredentialsLoader, SSL } from "./apis/google/CredentialsLoader";
+import YoutubeApi from "./apis/youtube/youtubeApiSample";
+import { Client } from "./Client";
+import { Database } from "./database";
 import { DocumentsCollection } from "./IDatabase";
-import { createServer, Server } from "https";
-import * as express from "express";
+import { Diff, GestureContent, MessageStore, MobileDocumentUploadContent, MobileInkOverlayContent, Transferable, Types, UpdateMobileInkOverlayPositionContent, YoutubeQueryInput, YoutubeQueryTypes } from "./Message";
+import { Search } from "./Search";
 import { resolvedPorts } from './server_Initialization';
 
 export namespace WebSocket {
-- 
cgit v1.2.3-70-g09d2


From ac177d7b9a01075fbf1ad1c327c7625d95569afb Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Sun, 2 Aug 2020 18:20:59 -0500
Subject: bug fixes found with sally

---
 src/client/views/PropertiesButtons.scss            | 13 +++++++--
 src/client/views/PropertiesButtons.tsx             | 29 +++++++++++++------
 src/client/views/collections/CollectionMenu.scss   | 19 ++++++++-----
 .../views/collections/CollectionTreeView.tsx       |  2 +-
 src/client/views/collections/CollectionView.tsx    |  2 +-
 .../collectionFreeForm/PropertiesView.scss         | 24 ++++++++++++++++
 .../collectionFreeForm/PropertiesView.tsx          | 33 ++++++++++------------
 src/client/views/nodes/DocumentView.tsx            |  8 +++---
 src/client/views/nodes/FontIconBox.scss            |  2 +-
 src/client/views/nodes/FontIconBox.tsx             | 23 ++++++++-------
 src/client/views/nodes/LabelBox.tsx                |  2 +-
 11 files changed, 103 insertions(+), 54 deletions(-)

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

diff --git a/src/client/views/PropertiesButtons.scss b/src/client/views/PropertiesButtons.scss
index e099122c4..b3a317a6b 100644
--- a/src/client/views/PropertiesButtons.scss
+++ b/src/client/views/PropertiesButtons.scss
@@ -77,10 +77,19 @@ $linkGap : 3px;
     text-align: center;
     border-radius: 5px;
     pointer-events: auto;
-    color: $dark-color;
-    border: $dark-color 1px solid;
+    // color: $dark-color;
+    // border: $dark-color 1px solid;
+    background-color: #252b33;
+    color: #fcfbf7;
     transition: 0.2s ease all;
     margin-right: 5px;
+    padding-top: 5px;
+
+    &:hover {
+        background: $main-accent;
+        transform: scale(1.05);
+        cursor: pointer;
+    }
 }
 
 .propertiesButtons-linker:hover {
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index 59e7cc7c8..d3f056a34 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -208,7 +208,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         const isPinned = targetDoc && Doc.isDocPinned(targetDoc);
         return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}</div></>}>
             <div className="propertiesButtons-linker"
-                style={{ backgroundColor: isPinned ? "white" : "rgb(37, 43, 51)", color: isPinned ? "black" : "white" }}
+                style={{ backgroundColor: isPinned ? "white" : "", color: isPinned ? "black" : "white" }}
                 onClick={e => DockedFrameRenderer.PinDoc(targetDoc, isPinned)}>
                 <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin"
                 />
@@ -238,6 +238,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     onAliasButtonDown = (e: React.PointerEvent): void => {
         setupMoveUpEvents(this, e, this.onAliasButtonMoved, emptyFunction, emptyFunction);
     }
+    @undoBatch
     onAliasButtonMoved = () => {
         if (this._dragRef.current) {
             const dragDocView = this.selectedDocumentView!;
@@ -273,12 +274,17 @@ export class PropertiesButtons extends React.Component<{}, {}> {
                 </div></Tooltip>;
     }
 
+    @undoBatch
     onCopy = () => {
         if (this.selectedDoc && this.selectedDocumentView) {
-            const copy = Doc.MakeCopy(this.selectedDocumentView.props.Document, true);
-            copy.x = NumCast(this.selectedDoc.x) + NumCast(this.selectedDoc._width);
-            copy.y = NumCast(this.selectedDoc.y) + 30;
-            this.selectedDocumentView.props.addDocument?.(copy);
+            // const copy = Doc.MakeCopy(this.selectedDocumentView.props.Document, true);
+            // copy.x = NumCast(this.selectedDoc.x) + NumCast(this.selectedDoc._width);
+            // copy.y = NumCast(this.selectedDoc.y) + 30;
+            // this.selectedDocumentView.props.addDocument?.(copy);
+            const alias = Doc.MakeAlias(this.selectedDoc);
+            alias.x = NumCast(this.selectedDoc.x) + NumCast(this.selectedDoc._width);
+            alias.y = NumCast(this.selectedDoc.y) + 30;
+            this.selectedDocumentView.props.addDocument?.(alias);
         }
     }
 
@@ -295,7 +301,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         </Tooltip>;
     }
 
-    @action
+    @action @undoBatch
     onLock = () => {
         this.selectedDocumentView?.toggleLockPosition();
     }
@@ -337,15 +343,19 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         return !targetDoc ? (null) : <Tooltip
             title={<><div className="dash-tooltip">{"Delete Document"}</div></>}>
             <div className={"propertiesButtons-linkButton-empty"}
-                onPointerDown={() => {
-                    this.selectedDocumentView?.props.ContainingCollectionView?.removeDocument(this.selectedDocumentView?.props.Document);
-                }}>
+                onPointerDown={this.deleteDocument}>
                 {<FontAwesomeIcon className="propertiesButtons-icon"
                     icon="trash-alt" size="sm" />}
             </div>
         </Tooltip>;
     }
 
+    @undoBatch
+    @action
+    deleteDocument = () => {
+        this.selectedDocumentView?.props.ContainingCollectionView?.removeDocument(this.selectedDocumentView?.props.Document);
+    }
+
     @computed
     get sharingButton() {
         const targetDoc = this.selectedDoc;
@@ -380,6 +390,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         }
     }
 
+    @undoBatch
     @action
     handleOptionChange = (e: any) => {
         const value = e.target.value;
diff --git a/src/client/views/collections/CollectionMenu.scss b/src/client/views/collections/CollectionMenu.scss
index 9da204787..0a316317f 100644
--- a/src/client/views/collections/CollectionMenu.scss
+++ b/src/client/views/collections/CollectionMenu.scss
@@ -2,8 +2,8 @@
 
 
 .collectionMenu-cont {
-    position:relative;
-    display:inline-flex;
+    position: relative;
+    display: inline-flex;
     width: 100%;
     opacity: 0.9;
     z-index: 9001;
@@ -12,14 +12,15 @@
     color: white;
     transform-origin: top left;
     top: 0;
-    width:100%;
+    width: 100%;
 
     .antimodeMenu-button {
         padding: 0;
         width: 30px;
         display: flex;
+
         svg {
-            margin:auto;
+            margin: auto;
         }
     }
 
@@ -108,6 +109,7 @@
                 margin-top: auto;
                 margin-bottom: auto;
             }
+
             .collectionViewBaseChrome-viewSpecs {
                 margin-left: 5px;
                 display: grid;
@@ -318,12 +320,14 @@
         text-align: center;
         display: block;
     }
+
     .color-previewI {
         width: 80%;
         height: 20%;
         bottom: 0;
         position: absolute;
     }
+
     .color-previewII {
         width: 80%;
         height: 80%;
@@ -336,7 +340,7 @@
         margin: auto;
         /* Make the buttons appear below each other */
     }
-    
+
     .btn-draw {
         display: inline-flex;
         margin: auto;
@@ -374,6 +378,7 @@
             display: block;
             margin: auto;
         }
+
         border-right: solid gray 1px;
     }
 }
@@ -398,14 +403,14 @@
 
     .collectionSchemaViewChrome-toggler {
         width: 100px;
-        height: 41px;
+        height: 35px;
         background-color: black;
         position: relative;
     }
 
     .collectionSchemaViewChrome-togglerButton {
         width: 47px;
-        height: 35px;
+        height: 30px;
         background-color: $light-color-secondary;
         // position: absolute;
         transition: all 0.5s ease;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 7787a8b38..3c7471d7c 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -785,7 +785,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
         onClicks.push({
             description: "Edit onChecked Script", event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.doc, undefined, "onCheckedClick"), "edit onCheckedClick"), icon: "edit"
         });
-        !existingOnClick && ContextMenu.Instance.addItem({ description: "OnClick...", noexpand: true, subitems: onClicks, icon: "hand-point-right" });
+        !existingOnClick && ContextMenu.Instance.addItem({ description: "OnClick...", noexpand: true, subitems: onClicks, icon: "mouse-pointer" });
     }
     outerXf = () => Utils.GetScreenTransform(this._mainEle!);
     onTreeDrop = (e: React.DragEvent) => this.onExternalDrop(e, {});
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index c2b55d38e..89034a0c0 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -339,7 +339,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
                     icon: "edit",
                     event: () => Doc.GetProto(this.props.Document)[StrCast(childClick.targetScriptKey)] = ObjectField.MakeCopy(ScriptCast(childClick.data)),
                 }));
-            !existingOnClick && cm.addItem({ description: "OnClick...", noexpand: true, subitems: onClicks, icon: "hand-point-right" });
+            !existingOnClick && cm.addItem({ description: "OnClick...", noexpand: true, subitems: onClicks, icon: "mouse-pointer" });
 
             if (!Doc.UserDoc().noviceMode) {
                 const more = cm.findByDescription("More...");
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index a96716659..7df56115f 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -60,6 +60,10 @@
             padding-left: 8px;
             background-color: rgb(51, 51, 51);
 
+            &:hover {
+                cursor: pointer;
+            }
+
             .propertiesView-settings-title-icon {
                 float: right;
                 right: 0;
@@ -94,6 +98,10 @@
             padding-left: 8px;
             background-color: rgb(51, 51, 51);
 
+            &:hover {
+                cursor: pointer;
+            }
+
             .propertiesView-sharing-title-icon {
                 float: right;
                 right: 0;
@@ -127,6 +135,10 @@
             padding-left: 8px;
             background-color: rgb(51, 51, 51);
 
+            &:hover {
+                cursor: pointer;
+            }
+
             .propertiesView-appearance-title-icon {
                 float: right;
                 right: 0;
@@ -160,6 +172,10 @@
             padding-left: 8px;
             background-color: rgb(51, 51, 51);
 
+            &:hover {
+                cursor: pointer;
+            }
+
             .propertiesView-transform-title-icon {
                 float: right;
                 right: 0;
@@ -287,6 +303,10 @@
             padding-left: 8px;
             background-color: rgb(51, 51, 51);
 
+            &:hover {
+                cursor: pointer;
+            }
+
             .propertiesView-fields-title-name {
                 font-size: 12.5px;
                 font-weight: bold;
@@ -362,6 +382,10 @@
             padding-left: 8px;
             background-color: rgb(51, 51, 51);
 
+            &:hover {
+                cursor: pointer;
+            }
+
             .propertiesView-layout-title-icon {
                 float: right;
                 right: 0;
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 73f0f1bdd..0168c825f 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -205,7 +205,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         }
     }
 
-
+    @undoBatch
     setKeyValue = (value: string) => {
         if (this.selectedDoc && this.dataDoc) {
             const doc = this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc;
@@ -266,9 +266,14 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         }
     }
 
+    @undoBatch
+    changePermissions = (e: any, user: string) => {
+        SharingManager.Instance.shareFromPropertiesSidebar(user, e.currentTarget.value as SharingPermissions, this.selectedDoc!);
+    }
+
     getPermissionsSelect(user: string) {
         return <select className="permissions-select"
-            onChange={e => SharingManager.Instance.shareFromPropertiesSidebar(user, e.currentTarget.value as SharingPermissions, this.selectedDoc!)}>
+            onChange={e => this.changePermissions(e, user)}>
             {Object.values(SharingPermissions).map(permission => {
                 return (
                     <option key={permission} value={permission} selected={this.selectedDoc![`ACL-${user.replace(".", "_")}`] === permission}>
@@ -344,6 +349,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         />;
     }
 
+    @undoBatch
     @action
     toggleCheckbox = () => {
         this.layoutFields = !this.layoutFields;
@@ -359,6 +365,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
             SetValue={this.setTitle} />;
     }
 
+    @undoBatch
     @action
     setTitle = (value: string) => {
         if (this.dataDoc) {
@@ -370,13 +377,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
 
-
-
-
-
-
-
-
     @undoBatch
     @action
     rotate = (angle: number) => {
@@ -739,9 +739,13 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
         if (!this.selectedDoc) {
             return <div className="propertiesView" style={{ width: this.props.width }}>
-                <div className="propertiesView-title" style={{ width: this.props.width, paddingLeft: 6 }}>
+                <div className="propertiesView-title" style={{ width: this.props.width }}>
                     No Document Selected
-            </div> </div>;
+                <div className="propertiesView-title-icon" onPointerDown={this.props.onDown}>
+                        <FontAwesomeIcon icon="times" color="black" size="xs" />
+                    </div>
+                </div>
+            </div>;
         }
 
         const novice = Doc.UserDoc().noviceMode;
@@ -783,9 +787,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 </div> : null}
             </div>
 
-
-
-
             {this.isInk ? <div className="propertiesView-appearance">
                 <div className="propertiesView-appearance-title"
                     onPointerDown={() => runInAction(() => { this.openAppearance = !this.openAppearance; })}
@@ -814,10 +815,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 </div> : null}
             </div> : null}
 
-
-
-
-
             <div className="propertiesView-fields">
                 <div className="propertiesView-fields-title"
                     onPointerDown={() => runInAction(() => { this.openFields = !this.openFields; })}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 30382a4ef..ec0a5f3ac 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -677,10 +677,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
     @action
     onCopy = () => {
-        const copy = Doc.MakeCopy(this.props.Document, true);
-        copy.x = NumCast(this.props.Document.x) + NumCast(this.props.Document._width);
-        copy.y = NumCast(this.props.Document.y) + 30;
-        this.props.addDocument?.(copy);
+        const alias = Doc.MakeAlias(this.props.Document);
+        alias.x = NumCast(this.props.Document.x) + NumCast(this.props.Document._width);
+        alias.y = NumCast(this.props.Document.y) + 30;
+        this.props.addDocument?.(alias);
     }
 
     @action
diff --git a/src/client/views/nodes/FontIconBox.scss b/src/client/views/nodes/FontIconBox.scss
index 13af511a6..a142d873a 100644
--- a/src/client/views/nodes/FontIconBox.scss
+++ b/src/client/views/nodes/FontIconBox.scss
@@ -33,7 +33,7 @@
     padding-left: 5px;
     width: 100%;
     width: 60px;
-    height: 70px;
+    height: 60px;
     padding-top: 3px;
     padding-bottom: 3px;
 
diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx
index 720d6a15d..7c538df92 100644
--- a/src/client/views/nodes/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox.tsx
@@ -66,18 +66,21 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>(
 
         if (this.layoutDoc.menuIcon) {
 
-            let backgroundColor = "black";
-            if (this.dataDoc.title === "Sharing" || this.dataDoc.title === "Help" || this.dataDoc.title === "Settings" || this.dataDoc.title === "Import") {
-                backgroundColor = "black";
-            } else {
-                backgroundColor = CurrentUserUtils.selectedPanel === this.dataDoc.title ? "lightgrey" : "black";
-            }
+            // let backgroundColor = "black";
+            // if (this.dataDoc.title === "Sharing" || this.dataDoc.title === "Help" || this.dataDoc.title === "Settings" || this.dataDoc.title === "Import") {
+            //     backgroundColor = "black";
+            // } else {
+            //     backgroundColor = CurrentUserUtils.selectedPanel === this.dataDoc.title ? "lightgrey" : "";
+            // }
 
-            const color = backgroundColor === "lightgrey" ? "black" : "white";
-            const menuBTN = <div className="menuButton" style={{ backgroundColor: backgroundColor }}>
+            const color = CurrentUserUtils.selectedPanel === this.dataDoc.title ? "black" : "white";
+            const menuBTN = <div className="menuButton"
+                style={{ backgroundColor: CurrentUserUtils.selectedPanel === this.dataDoc.title ? "lightgrey" : "" }}>
 
-                <div className="menuButton-wrap" style={{ backgroundColor: backgroundColor }}>
-                    <FontAwesomeIcon className="menuButton-icon" icon={StrCast(this.dataDoc.icon, "user") as any} color={color} size="lg" />
+                <div className="menuButton-wrap"
+                    style={{ backgroundColor: CurrentUserUtils.selectedPanel === this.dataDoc.title ? "lightgrey" : "" }}>
+                    <FontAwesomeIcon className="menuButton-icon"
+                        icon={StrCast(this.dataDoc.icon, "user") as any} color={color} size="lg" />
                     <div className="menuButton-label" style={{ color: color }}> {this.dataDoc.title} </div>
                 </div>
             </div>;
diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx
index 0dfbdc5cf..05ba6628c 100644
--- a/src/client/views/nodes/LabelBox.tsx
+++ b/src/client/views/nodes/LabelBox.tsx
@@ -41,7 +41,7 @@ export class LabelBox extends ViewBoxBaseComponent<FieldViewProps, LabelDocument
             }, icon: "trash"
         });
 
-        ContextMenu.Instance.addItem({ description: "OnClick...", noexpand: true, subitems: funcs, icon: "asterisk" });
+        ContextMenu.Instance.addItem({ description: "OnClick...", noexpand: true, subitems: funcs, icon: "mouse-pointer" });
     }
 
     @undoBatch
-- 
cgit v1.2.3-70-g09d2


From f4c14a48f91ec95b900bb1e25452d18971ff21a8 Mon Sep 17 00:00:00 2001
From: Geireann Lindfield Roberts <60007097+geireann@users.noreply.github.com>
Date: Mon, 3 Aug 2020 23:14:20 +0800
Subject: works with selection manager (PropertiesView)

---
 .../collectionFreeForm/PropertiesView.scss         | 42 +++++++++++-----------
 .../collectionFreeForm/PropertiesView.tsx          | 21 +++++++----
 src/client/views/nodes/PresBox.scss                |  2 +-
 src/client/views/nodes/PresBox.tsx                 |  2 +-
 .../views/presentationview/PresElementBox.tsx      |  2 +-
 5 files changed, 39 insertions(+), 30 deletions(-)

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

diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index 6283a6669..2cdaa25ee 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -543,6 +543,27 @@
     }
 }
 
+.propertiesView-presSelected {
+    border-top: solid 1px darkgrey;
+    width: 100%;
+    padding-top: 5px;
+    font-family: Roboto;
+    font-weight: 500;
+    display: inline-flex;
+
+    .propertiesView-selectedList {
+        border-left: solid 1px darkgrey;
+        margin-left: 10px;
+        padding-left: 5px;
+
+        .selectedList-items {
+            font-size: 12;
+            font-weight: 300;
+            margin-top: 1;
+        }
+    }
+}
+
 .widthAndDash {
 
     .width {
@@ -617,25 +638,4 @@
             margin-top: 2px;
         }
     }
-
-    .propertiesView-presSelected {
-        border-top: solid 1px darkgrey;
-        width: 100%;
-        padding-top: 5px;
-        font-family: Roboto;
-        font-weight: 500;
-        display: inline-flex;
-
-        .propertiesView-selectedList {
-            border-left: solid 1px darkgrey;
-            margin-left: 10px;
-            padding-left: 5px;
-
-            .selectedList-items {
-                font-size: 12;
-                font-weight: 300;
-                margin-top: 1;
-            }
-        }
-    }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index ce8baf559..88d585596 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -47,9 +47,14 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @computed get selectedDocumentView() {
         if (SelectionManager.SelectedDocuments().length) {
             return SelectionManager.SelectedDocuments()[0];
-        } else { console.log(undefined); return undefined; }
+        } else if (PresBox.Instance._selectedArray.length >= 1) {
+            return DocumentManager.Instance.getDocumentView(PresBox.Instance.rootDoc);
+        } else { return undefined; }
+    }
+    @computed get isPres(): boolean {
+        if (this.selectedDoc?.type === DocumentType.PRES) return true;
+        return false;
     }
-    @computed get isPres() { return this.selectedDoc?.type === DocumentType.PRES }
     @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; }
     @computed get dataDoc() { return this.selectedDocumentView?.dataDoc; }
 
@@ -748,10 +753,14 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     render() {
 
         if (!this.selectedDoc) {
-            return <div className="propertiesView" style={{ width: this.props.width }}>
-                <div className="propertiesView-title" style={{ width: this.props.width, paddingLeft: 6 }}>
-                    No Document Selected
-            </div> </div>;
+            console.log("!selectedDoc")
+            if (this.isPres === false) {
+                console.log("!isPres")
+                return <div className="propertiesView" style={{ width: this.props.width }}>
+                    <div className="propertiesView-title" style={{ width: this.props.width, paddingLeft: 6 }}>
+                        No Document Selected
+                </div> </div>;
+            }
         }
 
         const novice = Doc.UserDoc().noviceMode;
diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss
index e5878708f..83e7152a8 100644
--- a/src/client/views/nodes/PresBox.scss
+++ b/src/client/views/nodes/PresBox.scss
@@ -143,7 +143,7 @@
         display: grid;
         justify-content: flex-start;
         align-items: center;
-        grid-template-columns: repeat(auto-fit, 50px);
+        grid-template-columns: repeat(auto-fit, 70px);
     }
 
     .ribbon-property {
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index 618161e97..496d4666e 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -832,7 +832,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                             </div>
                         </div>
                         <div className="presBox-subheading" style={{ display: effect === 'None' ? "none" : "block" }}>Effect direction</div>
-                        <div className="presBox-reactiveGrid" style={{ display: effect === 'None' ? "none" : "grid", width: 40 }}>
+                        <div className="presBox-reactiveGrid" style={{ display: effect === 'None' ? "none" : "grid" }}>
                             <div className="effectDirection" style={{ display: "grid", width: 40 }}>
                                 <Tooltip title={<><div className="dash-tooltip">{"Enter from left"}</div></>}><div style={{ gridColumn: 1, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === "left" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'left'}><FontAwesomeIcon icon={"angle-right"} /></div></Tooltip>
                                 <Tooltip title={<><div className="dash-tooltip">{"Enter from right"}</div></>}><div style={{ gridColumn: 3, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === "right" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'right'}><FontAwesomeIcon icon={"angle-left"} /></div></Tooltip>
diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx
index 85949c5a8..ce7a43315 100644
--- a/src/client/views/presentationview/PresElementBox.tsx
+++ b/src/client/views/presentationview/PresElementBox.tsx
@@ -278,7 +278,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
                     } else if (e.shiftKey) {
                         PresBox.Instance.shiftSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!);
                     } else {
-                        this.props.focus(this.rootDoc);
+                        PresBox.Instance.selectElement(this.rootDoc);
                         PresBox.Instance._eleArray = [];
                         PresBox.Instance._eleArray.push(this._itemRef.current!);
                         PresBox.Instance._dragArray = [];
-- 
cgit v1.2.3-70-g09d2


From 48a65994e75fc0f2aaeb96807e8a4f58ff3e3968 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 3 Aug 2020 11:26:17 -0400
Subject: restored button next to tab for dragging document  & changed tab view

---
 .../views/collections/CollectionDockingView.scss   | 17 +++++--
 .../views/collections/CollectionDockingView.tsx    |  4 ++
 .../views/collections/ParentDocumentSelector.tsx   |  2 +-
 .../collectionFreeForm/PropertiesView.tsx          | 54 +++++++++++-----------
 4 files changed, 45 insertions(+), 32 deletions(-)

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

diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss
index 27d66f796..6ebd5103b 100644
--- a/src/client/views/collections/CollectionDockingView.scss
+++ b/src/client/views/collections/CollectionDockingView.scss
@@ -52,6 +52,20 @@
 
 .lm_header .lm_tab {
     padding-right: 20px;
+    margin-top: -1px;
+    border-bottom: 1px black;
+    .collectionDockingView-gear {
+        display: none;
+    }
+}
+
+.lm_header .lm_tab.lm_active {
+    padding-right: 20px;
+    margin-top: 1px;
+    border-bottom: unset;
+    .collectionDockingView-gear {
+        display: inline-block;
+    }
 }
 
 .lm_popout {
@@ -84,10 +98,7 @@
         padding-left: 5px;
         height: 15px;
         width: 18px;
-        display: inline-block;
         margin: auto;
-
-        display: none;
     }
 
     .collectionDockingView-dragAsDocument {
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 95b68a17d..533c8bffe 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -770,6 +770,10 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
     private onActiveContentItemChanged() {
         if (this.props.glContainer.tab) {
             this._isActive = this.props.glContainer.tab.isActive;
+            setTimeout(() => {
+                const dv = this._document && DocumentManager.Instance.getFirstDocumentView(this._document);
+                dv && SelectionManager.SelectDoc(dv, false);
+            });
             !this._isActive && this._document && Doc.UnBrushDoc(this._document); // bcz: bad -- trying to simulate a pointer leave event when a new tab is opened up on top of an existing one.
         }
     }
diff --git a/src/client/views/collections/ParentDocumentSelector.tsx b/src/client/views/collections/ParentDocumentSelector.tsx
index 532dd6abc..4c8cac3ed 100644
--- a/src/client/views/collections/ParentDocumentSelector.tsx
+++ b/src/client/views/collections/ParentDocumentSelector.tsx
@@ -129,7 +129,7 @@ export class DockingViewButtonSelector extends React.Component<{ views: () => Do
                 this.props.views()[0]?.select(false);
             }} className="buttonSelector">
             <Flyout anchorPoint={anchorPoints.LEFT_TOP} content={this.flyout} stylesheet={this.customStylesheet}>
-                <FontAwesomeIcon icon={"cog"} size={"sm"} />
+                <FontAwesomeIcon icon={"arrows-alt"} size={"sm"} />
             </Flyout>
         </span>;
     }
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 0168c825f..f5e0cd077 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -711,12 +711,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     @undoBatch @action
     changeDash = () => {
-        const dash = this.dashdStk;
-        if (dash === "2") {
-            this.dashdStk = "0";
-        } else {
-            this.dashdStk = "2";
-        }
+        this.dashdStk = this.dashdStk === "2" ? "0" : "2";
     }
 
     @computed get appearanceEditor() {
@@ -769,9 +764,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                         <FontAwesomeIcon icon={this.openActions ? "caret-down" : "caret-right"} size="lg" color="white" />
                     </div>
                 </div>
-                {this.openActions ? <div className="propertiesView-settings-content">
-                    <PropertiesButtons />
-                </div> : null}
+                {!this.openActions ? (null) :
+                    <div className="propertiesView-settings-content">
+                        <PropertiesButtons />
+                    </div>}
             </div>
             <div className="propertiesView-sharing">
                 <div className="propertiesView-sharing-title"
@@ -782,24 +778,27 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                         <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="white" />
                     </div>
                 </div>
-                {this.openSharing ? <div className="propertiesView-sharing-content">
-                    {this.sharingTable}
-                </div> : null}
+                {!this.openSharing ? (null) :
+                    <div className="propertiesView-sharing-content">
+                        {this.sharingTable}
+                    </div>}
             </div>
 
-            {this.isInk ? <div className="propertiesView-appearance">
-                <div className="propertiesView-appearance-title"
-                    onPointerDown={() => runInAction(() => { this.openAppearance = !this.openAppearance; })}
-                    style={{ backgroundColor: this.openAppearance ? "black" : "" }}>
-                    Appearance
-                    <div className="propertiesView-appearance-title-icon">
-                        <FontAwesomeIcon icon={this.openAppearance ? "caret-down" : "caret-right"} size="lg" color="white" />
+            {!this.isInk ? (null) :
+                <div className="propertiesView-appearance">
+                    <div className="propertiesView-appearance-title"
+                        onPointerDown={() => runInAction(() => { this.openAppearance = !this.openAppearance; })}
+                        style={{ backgroundColor: this.openAppearance ? "black" : "" }}>
+                        Appearance
+                        <div className="propertiesView-appearance-title-icon">
+                            <FontAwesomeIcon icon={this.openAppearance ? "caret-down" : "caret-right"} size="lg" color="white" />
+                        </div>
                     </div>
-                </div>
-                {this.openAppearance ? <div className="propertiesView-appearance-content">
-                    {this.appearanceEditor}
-                </div> : null}
-            </div> : null}
+                    {!this.openAppearance ? (null) :
+                        <div className="propertiesView-appearance-content">
+                            {this.appearanceEditor}
+                        </div>}
+                </div>}
 
             {this.isInk ? <div className="propertiesView-transform">
                 <div className="propertiesView-transform-title"
@@ -830,18 +829,17 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                     {this.fieldsCheckbox}
                     <div className="propertiesView-fields-checkbox-text">Layout</div>
                 </div> : null}
-                {this.openFields ?
+                {!this.openFields ? (null) :
                     <div className="propertiesView-fields-content">
                         {novice ? this.noviceFields : this.expandedField}
-                    </div> : null}
+                    </div>}
             </div>
             <div className="propertiesView-layout">
                 <div className="propertiesView-layout-title"
                     onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}
                     style={{ backgroundColor: this.openLayout ? "black" : "" }}>
                     Layout
-                    <div className="propertiesView-layout-title-icon"
-                        onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}>
+                    <div className="propertiesView-layout-title-icon" onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}>
                         <FontAwesomeIcon icon={this.openLayout ? "caret-down" : "caret-right"} size="lg" color="white" />
                     </div>
                 </div>
-- 
cgit v1.2.3-70-g09d2


From 8019926f41d0be85a21dfa9ad0d1a0d9e7160935 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Mon, 3 Aug 2020 18:10:55 -0500
Subject: menu buttons and other UI changes

---
 src/client/views/MainView.scss                     |   3 +-
 src/client/views/MainView.tsx                      |   4 +-
 src/client/views/PropertiesButtons.scss            |  30 +-
 src/client/views/PropertiesButtons.tsx             | 351 ++++++++++++---------
 .../collectionFreeForm/PropertiesView.scss         |   2 +-
 .../collectionFreeForm/PropertiesView.tsx          | 176 ++++++-----
 6 files changed, 320 insertions(+), 246 deletions(-)

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

diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index a57d22afd..e9e700ba8 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -155,7 +155,7 @@
 .mainView-menuPanel {
 
     width: 60px;
-    background-color: black;
+    background-color: #121721;
     height: 100%;
     //overflow-y: scroll;
     //overflow-x: hidden;
@@ -165,6 +165,7 @@
         padding: 7px;
         padding-left: 7px;
         width: 100%;
+        background: black;
 
         .mainView-menuPanel-button-wrap {
             width: 45px;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index ca5154ef7..93cc95ba4 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -415,10 +415,10 @@ export class MainView extends React.Component {
         if (!this.sidebarContent) return null;
         return <div className="mainView-libraryFlyout">
             <div className="mainView-contentArea" style={{ position: "relative", height: `100%`, width: "100%", overflow: "visible" }}>
-                {this.flyoutWidth > 0 ? <div className="mainView-libraryFlyout-close"
+                {/* {this.flyoutWidth > 0 ? <div className="mainView-libraryFlyout-close"
                     onPointerDown={this.closeFlyout}>
                     <FontAwesomeIcon icon="times" color="black" size="lg" />
-                </div> : null}
+                </div> : null} */}
 
                 <DocumentView
                     Document={this.sidebarContent}
diff --git a/src/client/views/PropertiesButtons.scss b/src/client/views/PropertiesButtons.scss
index 1cba252de..5edaa2168 100644
--- a/src/client/views/PropertiesButtons.scss
+++ b/src/client/views/PropertiesButtons.scss
@@ -21,9 +21,8 @@ $linkGap : 3px;
 .propertiesButtons-linkButton-empty,
 .propertiesButtons-linkButton-nonempty {
     height: 30px;
-    width: 30px;
-    border-radius: 5px;
-    opacity: 0.9;
+    width: 32px;
+    border-radius: 6px;
     pointer-events: auto;
     background-color: #121721;
     color: #fcfbf7;
@@ -36,6 +35,7 @@ $linkGap : 3px;
     justify-content: center;
     align-items: center;
     margin-right: 10px;
+    margin-left: 3.5px;
 
     &:hover {
         background: $main-accent;
@@ -68,23 +68,35 @@ $linkGap : 3px;
     padding-right: 5px;
     width: 25px;
     border-radius: 5px;
-    margin-right: 18px;
+    margin-right: 22px;
     margin-bottom: 8px;
 }
 
+.propertiesButtons-title {
+    background: #121721;
+    color: white;
+    font-size: 6px;
+    width: 40px;
+    padding: 5px;
+    height: 16px;
+    border-radius: 7px;
+    text-transform: uppercase;
+    text-align: center;
+    margin-top: -4px;
+}
+
 .propertiesButtons-linker {
     height: 30px;
-    width: 30px;
+    width: 32px;
     text-align: center;
-    border-radius: 5px;
+    border-radius: 6px;
     pointer-events: auto;
-    // color: $dark-color;
-    // border: $dark-color 1px solid;
-    background-color: #252b33;
+    background-color: #121721;
     color: #fcfbf7;
     transition: 0.2s ease all;
     margin-right: 5px;
     padding-top: 5px;
+    margin-left: 3.5px;
 
     &:hover {
         background: $main-accent;
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index d46c03470..37ee3d9e0 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -128,18 +128,22 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         const targetDoc = this.selectedDoc;
         const published = targetDoc && Doc.GetProto(targetDoc)[GoogleRef] !== undefined;
         const animation = this.isAnimatingPulse ? "shadow-pulse 1s linear infinite" : "none";
-        return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{`${published ? "Push" : "Publish"} to Google Docs`}</div></>}>
-            <div
-                className="propertiesButtons-linker"
-                style={{ animation }}
-                onClick={async () => {
-                    await GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken();
-                    !published && runInAction(() => this.isAnimatingPulse = true);
-                    PropertiesButtons.hasPushedHack = false;
-                    targetDoc[Pushes] = NumCast(targetDoc[Pushes]) + 1;
-                }}>
-                <FontAwesomeIcon className="documentdecorations-icon" icon={published ? (this.pushIcon as any) : cloud} size={published ? "sm" : "xs"} />
-            </div></Tooltip>;
+        return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{`${published ? "Push" : "Publish"} to Google Docs`}</div></>} placement="top">
+            <div>
+                <div
+                    className="propertiesButtons-linker"
+                    style={{ animation }}
+                    onClick={async () => {
+                        await GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken();
+                        !published && runInAction(() => this.isAnimatingPulse = true);
+                        PropertiesButtons.hasPushedHack = false;
+                        targetDoc[Pushes] = NumCast(targetDoc[Pushes]) + 1;
+                    }}>
+                    <FontAwesomeIcon className="documentdecorations-icon" icon={published ? (this.pushIcon as any) : cloud} size={published ? "lg" : "sm"} />
+                </div>
+                <div className="propertiesButtons-title">Google</div>
+            </div>
+        </Tooltip>;
     }
 
     @computed
@@ -158,74 +162,88 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         })();
 
         return !targetDoc || !dataDoc || !dataDoc[GoogleRef] ? (null) : <Tooltip
-            title={<><div className="dash-tooltip">{title}</div></>}>
-            <div className="propertiesButtons-linker"
-                style={{ backgroundColor: this.pullColor }}
-                onPointerEnter={action(e => {
-                    if (e.altKey) {
-                        this.openHover = UtilityButtonState.OpenExternally;
-                    } else if (e.shiftKey) {
-                        this.openHover = UtilityButtonState.OpenRight;
-                    }
-                })}
-                onPointerLeave={action(() => this.openHover = UtilityButtonState.Default)}
-                onClick={async e => {
-                    const googleDocUrl = `https://docs.google.com/document/d/${dataDoc[GoogleRef]}/edit`;
-                    if (e.shiftKey) {
-                        e.preventDefault();
-                        let googleDoc = await Cast(dataDoc.googleDoc, Doc);
-                        if (!googleDoc) {
-                            const options = { _width: 600, _nativeWidth: 960, _nativeHeight: 800, isAnnotating: false, UseCors: false };
-                            googleDoc = Docs.Create.WebDocument(googleDocUrl, options);
-                            dataDoc.googleDoc = googleDoc;
+            title={<><div className="dash-tooltip">{title}</div></>} placement="top">
+            <div>
+                <div className="propertiesButtons-linker"
+                    style={{ backgroundColor: this.pullColor }}
+                    onPointerEnter={action(e => {
+                        if (e.altKey) {
+                            this.openHover = UtilityButtonState.OpenExternally;
+                        } else if (e.shiftKey) {
+                            this.openHover = UtilityButtonState.OpenRight;
                         }
-                        CollectionDockingView.AddRightSplit(googleDoc);
-                    } else if (e.altKey) {
-                        e.preventDefault();
-                        window.open(googleDocUrl);
-                    } else {
-                        this.clearPullColor();
-                        PropertiesButtons.hasPulledHack = false;
-                        targetDoc[Pulls] = NumCast(targetDoc[Pulls]) + 1;
-                        dataDoc.unchanged && runInAction(() => this.isAnimatingFetch = true);
-                    }
-                }}>
-                <FontAwesomeIcon className="documentdecorations-icon" size="sm"
-                    style={{ WebkitAnimation: animation, MozAnimation: animation }}
-                    icon={(() => {
-                        switch (this.openHover) {
-                            default:
-                            case UtilityButtonState.Default: return dataDoc.unchanged === false ? (this.pullIcon as any) : fetch;
-                            case UtilityButtonState.OpenRight: return "arrow-alt-circle-right";
-                            case UtilityButtonState.OpenExternally: return "share";
+                    })}
+                    onPointerLeave={action(() => this.openHover = UtilityButtonState.Default)}
+                    onClick={async e => {
+                        const googleDocUrl = `https://docs.google.com/document/d/${dataDoc[GoogleRef]}/edit`;
+                        if (e.shiftKey) {
+                            e.preventDefault();
+                            let googleDoc = await Cast(dataDoc.googleDoc, Doc);
+                            if (!googleDoc) {
+                                const options = { _width: 600, _nativeWidth: 960, _nativeHeight: 800, isAnnotating: false, UseCors: false };
+                                googleDoc = Docs.Create.WebDocument(googleDocUrl, options);
+                                dataDoc.googleDoc = googleDoc;
+                            }
+                            CollectionDockingView.AddRightSplit(googleDoc);
+                        } else if (e.altKey) {
+                            e.preventDefault();
+                            window.open(googleDocUrl);
+                        } else {
+                            this.clearPullColor();
+                            PropertiesButtons.hasPulledHack = false;
+                            targetDoc[Pulls] = NumCast(targetDoc[Pulls]) + 1;
+                            dataDoc.unchanged && runInAction(() => this.isAnimatingFetch = true);
                         }
-                    })()}
-                />
-            </div></Tooltip>;
+                    }}>
+                    <FontAwesomeIcon className="documentdecorations-icon" size="lg"
+                        style={{ WebkitAnimation: animation, MozAnimation: animation }}
+                        icon={(() => {
+                            switch (this.openHover) {
+                                default:
+                                case UtilityButtonState.Default: return dataDoc.unchanged === false ? (this.pullIcon as any) : fetch;
+                                case UtilityButtonState.OpenRight: return "arrow-alt-circle-right";
+                                case UtilityButtonState.OpenExternally: return "share";
+                            }
+                        })()}
+                    />
+                </div>
+                <div className="propertiesButtons-title">Fetch</div>
+            </div>
+        </Tooltip>;
     }
     @computed
     get pinButton() {
         const targetDoc = this.selectedDoc;
         const isPinned = targetDoc && Doc.isDocPinned(targetDoc);
-        return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}</div></>}>
-            <div className="propertiesButtons-linker"
-                style={{ backgroundColor: isPinned ? "white" : "", color: isPinned ? "black" : "white" }}
-                onClick={e => DockedFrameRenderer.PinDoc(targetDoc, isPinned)}>
-                <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin"
-                />
-            </div></Tooltip>;
+        return !targetDoc ? (null) : <Tooltip
+            title={<><div className="dash-tooltip">{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" :
+                "Pin to presentation"}</div></>} placement="top">
+            <div>
+                <div className="propertiesButtons-linker"
+                    style={{ backgroundColor: isPinned ? "white" : "", color: isPinned ? "black" : "white" }}
+                    onClick={e => DockedFrameRenderer.PinDoc(targetDoc, isPinned)}>
+                    <FontAwesomeIcon className="documentdecorations-icon" size="lg" icon="map-pin"
+                    />
+                </div>
+
+                <div className="propertiesButtons-title">{Doc.isDocPinned(targetDoc) ? "Unpin" : "Pin"}</div>
+            </div>
+        </Tooltip>;
     }
 
     @computed
     get metadataButton() {
         //const view0 = this.view0;
         if (this.selectedDoc) {
-            return <Tooltip title={<><div className="dash-tooltip">Show metadata panel</div></>}>
+            return <Tooltip title={<><div className="dash-tooltip">Show metadata panel</div></>} placement="top">
                 <div className="propertiesButtons-linkFlyout">
                     <Flyout anchorPoint={anchorPoints.LEFT_TOP}
                         content={<MetadataEntryMenu docs={[this.selectedDoc]} suggestWithFunction />  /* tfs: @bcz This might need to be the data document? */}>
-                        <div className={"propertiesButtons-linkButton-" + "empty"} onPointerDown={e => e.stopPropagation()} >
-                            {<FontAwesomeIcon className="documentdecorations-icon" icon="tag" size="sm" />}
+                        <div>
+                            <div className={"propertiesButtons-linkButton-" + "empty"} onPointerDown={e => e.stopPropagation()} >
+                                {<FontAwesomeIcon className="documentdecorations-icon" icon="tag" size="lg" />}
+                            </div>
+                            <div className="propertiesButtons-title">Metadata</div>
                         </div>
                     </Flyout>
                 </div></Tooltip>;
@@ -264,12 +282,15 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         Array.from(Object.values(Templates.TemplateList)).map(template =>
             templates.set(template, views.reduce((checked, doc) => checked || doc?.props.Document["_show" + template.Name] ? true : false, false as boolean)));
         return !docView ? (null) :
-            <Tooltip title={<><div className="dash-tooltip">Customize layout</div></>}>
+            <Tooltip title={<><div className="dash-tooltip">Customize layout</div></>} placement="top">
                 <div className="propertiesButtons-linkFlyout">
                     <Flyout anchorPoint={anchorPoints.LEFT_TOP} //onOpen={action(() => this._aliasDown = true)} onClose={action(() => this._aliasDown = false)}
                         content={<TemplateMenu docViews={views.filter(v => v).map(v => v as DocumentView)} templates={templates} />}>
-                        <div className={"propertiesButtons-linkButton-empty"} >
-                            {<FontAwesomeIcon className="documentdecorations-icon" icon="edit" size="sm" />}
+                        <div>
+                            <div className={"propertiesButtons-linkButton-empty"} >
+                                {<FontAwesomeIcon className="documentdecorations-icon" icon="edit" size="lg" />}
+                            </div>
+                            <div className="propertiesButtons-title">Layout</div>
                         </div>
                     </Flyout>
                 </div></Tooltip>;
@@ -292,12 +313,15 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     @computed
     get copyButton() {
         const targetDoc = this.selectedDoc;
-        return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Tap or Drag to create an alias"}</div></>}>
-            <div className={"propertiesButtons-linkButton-empty"}
-                ref={this._dragRef}
-                onPointerDown={this.onAliasButtonDown}
-                onClick={this.onCopy}>
-                {<FontAwesomeIcon className="documentdecorations-icon" icon="copy" size="sm" />}
+        return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Tap or Drag to create an alias"}</div></>} placement="top">
+            <div>
+                <div className={"propertiesButtons-linkButton-empty"}
+                    ref={this._dragRef}
+                    onPointerDown={this.onAliasButtonDown}
+                    onClick={this.onCopy}>
+                    {<FontAwesomeIcon className="documentdecorations-icon" icon="copy" size="lg" />}
+                </div>
+                <div className="propertiesButtons-title">Alias</div>
             </div>
         </Tooltip>;
     }
@@ -312,11 +336,14 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         const targetDoc = this.selectedDoc;
         return !targetDoc ? (null) : <Tooltip
             title={<><div className="dash-tooltip">{this.selectedDoc?.lockedPosition ?
-                "Unlock Position" : "Lock Position"}</div></>}>
-            <div className={"propertiesButtons-linkButton-empty"}
-                onPointerDown={this.onLock} >
-                {<FontAwesomeIcon className="documentdecorations-icon"
-                    icon={BoolCast(this.selectedDoc?.lockedPosition) ? "unlock" : "lock"} size="sm" />}
+                "Unlock Position" : "Lock Position"}</div></>} placement="top">
+            <div>
+                <div className={"propertiesButtons-linkButton-empty"}
+                    onPointerDown={this.onLock} >
+                    {<FontAwesomeIcon className="documentdecorations-icon"
+                        icon={BoolCast(this.selectedDoc?.lockedPosition) ? "unlock" : "lock"} size="lg" />}
+                </div>
+                <div className="propertiesButtons-title">Position </div>
             </div>
         </Tooltip>;
     }
@@ -325,15 +352,18 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     get downloadButton() {
         const targetDoc = this.selectedDoc;
         return !targetDoc ? (null) : <Tooltip
-            title={<><div className="dash-tooltip">{"Download Document"}</div></>}>
-            <div className={"propertiesButtons-linkButton-empty"}
-                onPointerDown={async () => {
-                    if (this.selectedDocumentView?.props.Document) {
-                        Doc.Zip(this.selectedDocumentView?.props.Document);
-                    }
-                }}>
-                {<FontAwesomeIcon className="propertiesButtons-icon"
-                    icon="download" size="sm" />}
+            title={<><div className="dash-tooltip">{"Download Document"}</div></>} placement="top">
+            <div>
+                <div className={"propertiesButtons-linkButton-empty"}
+                    onPointerDown={async () => {
+                        if (this.selectedDocumentView?.props.Document) {
+                            Doc.Zip(this.selectedDocumentView?.props.Document);
+                        }
+                    }}>
+                    {<FontAwesomeIcon className="propertiesButtons-icon"
+                        icon="download" size="lg" />}
+                </div>
+                <div className="propertiesButtons-title"> downld </div>
             </div>
         </Tooltip>;
     }
@@ -342,11 +372,14 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     get deleteButton() {
         const targetDoc = this.selectedDoc;
         return !targetDoc ? (null) : <Tooltip
-            title={<><div className="dash-tooltip">{"Delete Document"}</div></>}>
-            <div className={"propertiesButtons-linkButton-empty"}
-                onPointerDown={this.deleteDocument}>
-                {<FontAwesomeIcon className="propertiesButtons-icon"
-                    icon="trash-alt" size="sm" />}
+            title={<><div className="dash-tooltip">{"Delete Document"}</div></>} placement="top">
+            <div>
+                <div className={"propertiesButtons-linkButton-empty"}
+                    onPointerDown={this.deleteDocument}>
+                    {<FontAwesomeIcon className="propertiesButtons-icon"
+                        icon="trash-alt" size="lg" />}
+                </div>
+                <div className="propertiesButtons-title"> delete </div>
             </div>
         </Tooltip>;
     }
@@ -361,15 +394,18 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     get sharingButton() {
         const targetDoc = this.selectedDoc;
         return !targetDoc ? (null) : <Tooltip
-            title={<><div className="dash-tooltip">{"Share Document"}</div></>}>
-            <div className={"propertiesButtons-linkButton-empty"}
-                onPointerDown={() => {
-                    if (this.selectedDocumentView) {
-                        SharingManager.Instance.open(this.selectedDocumentView);
-                    }
-                }}>
-                {<FontAwesomeIcon className="propertiesButtons-icon"
-                    icon="users" size="sm" />}
+            title={<><div className="dash-tooltip">{"Share Document"}</div></>} placement="top">
+            <div>
+                <div className={"propertiesButtons-linkButton-empty"}
+                    onPointerDown={() => {
+                        if (this.selectedDocumentView) {
+                            SharingManager.Instance.open(this.selectedDocumentView);
+                        }
+                    }}>
+                    {<FontAwesomeIcon className="propertiesButtons-icon"
+                        icon="users" size="lg" />}
+                </div>
+                <div className="propertiesButtons-title"> share </div>
             </div>
         </Tooltip>;
     }
@@ -377,15 +413,19 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     @computed
     get onClickButton() {
         if (this.selectedDoc) {
-            return <Tooltip title={<><div className="dash-tooltip">Choose onClick behavior</div></>}>
-                <div className="propertiesButtons-linkFlyout">
-                    <Flyout anchorPoint={anchorPoints.LEFT_TOP}
-                        content={this.onClickFlyout}>
-                        <div className={"propertiesButtons-linkButton-" + "empty"} onPointerDown={e => e.stopPropagation()} >
-                            {<FontAwesomeIcon className="documentdecorations-icon" icon="mouse-pointer" size="sm" />}
-                        </div>
-                    </Flyout>
-                </div></Tooltip>;
+            return <Tooltip title={<><div className="dash-tooltip">Choose onClick behavior</div></>} placement="top">
+                <div>
+                    <div className="propertiesButtons-linkFlyout">
+                        <Flyout anchorPoint={anchorPoints.LEFT_TOP}
+                            content={this.onClickFlyout}>
+                            <div className={"propertiesButtons-linkButton-" + "empty"} onPointerDown={e => e.stopPropagation()} >
+                                {<FontAwesomeIcon className="documentdecorations-icon" icon="mouse-pointer" size="lg" />}
+                            </div>
+                        </Flyout>
+                    </div>
+                    <div className="propertiesButtons-title"> onclick </div>
+                </div>
+            </Tooltip>;
         } else {
             return null;
         }
@@ -472,15 +512,18 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     get googlePhotosButton() {
         const targetDoc = this.selectedDoc;
         return !targetDoc ? (null) : <Tooltip
-            title={<><div className="dash-tooltip">{"Export to Google Photos"}</div></>}>
-            <div className={"propertiesButtons-linkButton-empty"}
-                onPointerDown={() => {
-                    if (this.selectedDocumentView) {
-                        GooglePhotos.Export.CollectionToAlbum({ collection: this.selectedDocumentView.Document }).then(console.log);
-                    }
-                }}>
-                {<FontAwesomeIcon className="documentdecorations-icon"
-                    icon="cloud-upload-alt" size="sm" />}
+            title={<><div className="dash-tooltip">{"Export to Google Photos"}</div></>} placement="top">
+            <div>
+                <div className={"propertiesButtons-linkButton-empty"}
+                    onPointerDown={() => {
+                        if (this.selectedDocumentView) {
+                            GooglePhotos.Export.CollectionToAlbum({ collection: this.selectedDocumentView.Document }).then(console.log);
+                        }
+                    }}>
+                    {<FontAwesomeIcon className="documentdecorations-icon"
+                        icon="cloud-upload-alt" size="lg" />}
+                </div>
+                <div className="propertiesButtons-title"> google </div>
             </div>
         </Tooltip>;
     }
@@ -489,13 +532,16 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     get clustersButton() {
         const targetDoc = this.selectedDoc;
         return !targetDoc ? (null) : <Tooltip
-            title={<><div className="dash-tooltip">{this.selectedDoc?.useClusters ? "Stop Showing Clusters" : "Show Clusters"}</div></>}>
-            <div className={"propertiesButtons-linkButton-empty"}
-                style={{ backgroundColor: this.selectedDoc?.useClusters ? "#a0a0a0" : "" }}
-                onPointerDown={this.changeClusters}>
-                {<FontAwesomeIcon className="documentdecorations-icon"
-                    color={this.selectedDoc?.useClusters ? "black" : "white"}
-                    icon="braille" size="sm" />}
+            title={<><div className="dash-tooltip">{this.selectedDoc?.useClusters ? "Stop Showing Clusters" : "Show Clusters"}</div></>} placement="top">
+            <div>
+                <div className={"propertiesButtons-linkButton-empty"}
+                    style={{ backgroundColor: this.selectedDoc?.useClusters ? "#a0a0a0" : "" }}
+                    onPointerDown={this.changeClusters}>
+                    {<FontAwesomeIcon className="documentdecorations-icon"
+                        color={this.selectedDoc?.useClusters ? "black" : "white"}
+                        icon="braille" size="lg" />}
+                </div>
+                <div className="propertiesButtons-title"> clusters </div>
             </div>
         </Tooltip>;
     }
@@ -514,13 +560,16 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     get fitContentButton() {
         const targetDoc = this.selectedDoc;
         return !targetDoc ? (null) : <Tooltip
-            title={<><div className="dash-tooltip">{this.selectedDoc?._fitToBox ? "Stop Fitting Content" : "Fit Content"}</div></>}>
-            <div className={"propertiesButtons-linkButton-empty"}
-                style={{ backgroundColor: this.selectedDoc?._fitToBox ? "#a0a0a0" : "" }}
-                onPointerDown={this.changeFitToBox}>
-                {<FontAwesomeIcon className="documentdecorations-icon"
-                    color={this.selectedDoc?._fitToBox ? "black" : "white"}
-                    icon="expand" size="sm" />}
+            title={<><div className="dash-tooltip">{this.selectedDoc?._fitToBox ? "Stop Fitting Content" : "Fit Content"}</div></>} placement="top">
+            <div>
+                <div className={"propertiesButtons-linkButton-empty"}
+                    style={{ backgroundColor: this.selectedDoc?._fitToBox ? "#a0a0a0" : "" }}
+                    onPointerDown={this.changeFitToBox}>
+                    {<FontAwesomeIcon className="documentdecorations-icon"
+                        color={this.selectedDoc?._fitToBox ? "black" : "white"}
+                        icon="expand" size="lg" />}
+                </div>
+                <div className="propertiesButtons-title"> {this.selectedDoc?._fitToBox ? "unfit" : "fit"} </div>
             </div>
         </Tooltip>;
     }
@@ -541,11 +590,14 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     get maskButton() {
         const targetDoc = this.selectedDoc;
         return !targetDoc ? (null) : <Tooltip
-            title={<><div className="dash-tooltip">Make Mask</div></>}>
-            <div className={"propertiesButtons-linkButton-empty"}
-                onPointerDown={this.makeMask}>
-                {<FontAwesomeIcon className="documentdecorations-icon"
-                    color="white" icon="paint-brush" size="sm" />}
+            title={<><div className="dash-tooltip">Make Mask</div></>} placement="top">
+            <div>
+                <div className={"propertiesButtons-linkButton-empty"}
+                    onPointerDown={this.makeMask}>
+                    {<FontAwesomeIcon className="documentdecorations-icon"
+                        color="white" icon="paint-brush" size="lg" />}
+                </div>
+                <div className="propertiesButtons-title"> mask </div>
             </div>
         </Tooltip>;
     }
@@ -553,13 +605,16 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     @computed
     get contextButton() {
         if (this.selectedDoc) {
-            return <Tooltip title={<><div className="dash-tooltip">Show Context</div></>}>
-                <div className={"propertiesButtons-linkButton-empty"}>
-                    <ParentDocSelector Document={this.selectedDoc} addDocTab={(doc, where) => {
-                        where === "onRight" ? CollectionDockingView.AddRightSplit(doc) :
-                            this.selectedDocumentView?.props.addDocTab(doc, "onRight");
-                        return true;
-                    }} />
+            return <Tooltip title={<><div className="dash-tooltip">Show Context</div></>} placement="top">
+                <div>
+                    <div className={"propertiesButtons-linkButton-empty"}>
+                        <ParentDocSelector Document={this.selectedDoc} addDocTab={(doc, where) => {
+                            where === "onRight" ? CollectionDockingView.AddRightSplit(doc) :
+                                this.selectedDocumentView?.props.addDocTab(doc, "onRight");
+                            return true;
+                        }} />
+                    </div>
+                    <div className="propertiesButtons-title"> context </div>
                 </div>
             </Tooltip>;
         } else {
@@ -622,9 +677,6 @@ export class PropertiesButtons extends React.Component<{}, {}> {
             <div className="propertiesButtons-button">
                 {this.onClickButton}
             </div>
-            {/* <div className="propertiesButtons-button">
-                {this.contextButton}
-            </div> */}
             <div className="propertiesButtons-button">
                 {this.sharingButton}
             </div>
@@ -652,6 +704,9 @@ export class PropertiesButtons extends React.Component<{}, {}> {
             <div className="propertiesButtons-button" style={{ display: !isInk ? "none" : "" }}>
                 {this.maskButton}
             </div>
+            <div className="propertiesButtons-button">
+                {this.contextButton}
+            </div>
         </div>
         </div>;
     }
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index 7df56115f..aede3842e 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -41,7 +41,7 @@
         font-size: 12.5px;
 
         &:hover {
-            cursor: pointer;
+            cursor: text;
         }
     }
 
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index f5e0cd077..9c5b8f81d 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -59,6 +59,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @observable openAppearance: boolean = true;
     @observable openTransform: boolean = true;
 
+    @observable inActions: boolean = false;
+
     @computed get isInk() { return this.selectedDoc?.type === DocumentType.INK; }
 
     @action
@@ -736,115 +738,119 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
             return <div className="propertiesView" style={{ width: this.props.width }}>
                 <div className="propertiesView-title" style={{ width: this.props.width }}>
                     No Document Selected
-                <div className="propertiesView-title-icon" onPointerDown={this.props.onDown}>
-                        <FontAwesomeIcon icon="times" color="black" size="xs" />
-                    </div>
-                </div>
+            </div>
             </div>;
-        }
 
-        const novice = Doc.UserDoc().noviceMode;
+        } else {
+
+            const novice = Doc.UserDoc().noviceMode;
 
-        return <div className="propertiesView" style={{ width: this.props.width }} >
-            <div className="propertiesView-title" style={{ width: this.props.width }}>
-                Properties
-                <div className="propertiesView-title-icon" onPointerDown={this.props.onDown}>
+            return <div className="propertiesView" style={{
+                width: this.props.width,
+                // overflowY: this.inActions ? "visible" : "scroll"
+            }} >
+                <div className="propertiesView-title" style={{ width: this.props.width }}>
+                    Properties
+                {/* <div className="propertiesView-title-icon" onPointerDown={this.props.onDown}>
                     <FontAwesomeIcon icon="times" color="black" size="sm" />
+                </div> */}
                 </div>
-            </div>
-            <div className="propertiesView-name">
-                {this.editableTitle}
-            </div>
-            <div className="propertiesView-settings">
-                <div className="propertiesView-settings-title"
-                    onPointerDown={() => runInAction(() => { this.openActions = !this.openActions; })}
-                    style={{ backgroundColor: this.openActions ? "black" : "" }}>
-                    Actions
+                <div className="propertiesView-name">
+                    {this.editableTitle}
+                </div>
+                <div className="propertiesView-settings" onPointerEnter={() => runInAction(() => { this.inActions = true; })}
+                    onPointerLeave={() => runInAction(() => { this.inActions = false; })}>
+                    <div className="propertiesView-settings-title"
+                        onPointerDown={() => runInAction(() => { this.openActions = !this.openActions; })}
+                        style={{ backgroundColor: this.openActions ? "black" : "" }}>
+                        Actions
                     <div className="propertiesView-settings-title-icon">
-                        <FontAwesomeIcon icon={this.openActions ? "caret-down" : "caret-right"} size="lg" color="white" />
+                            <FontAwesomeIcon icon={this.openActions ? "caret-down" : "caret-right"} size="lg" color="white" />
+                        </div>
                     </div>
+                    {!this.openActions ? (null) :
+                        <div className="propertiesView-settings-content">
+                            <PropertiesButtons />
+                        </div>}
                 </div>
-                {!this.openActions ? (null) :
-                    <div className="propertiesView-settings-content">
-                        <PropertiesButtons />
-                    </div>}
-            </div>
-            <div className="propertiesView-sharing">
-                <div className="propertiesView-sharing-title"
-                    onPointerDown={() => runInAction(() => { this.openSharing = !this.openSharing; })}
-                    style={{ backgroundColor: this.openSharing ? "black" : "" }}>
-                    Sharing {"&"} Permissions
+                <div className="propertiesView-sharing">
+                    <div className="propertiesView-sharing-title"
+                        onPointerDown={() => runInAction(() => { this.openSharing = !this.openSharing; })}
+                        style={{ backgroundColor: this.openSharing ? "black" : "" }}>
+                        Sharing {"&"} Permissions
                     <div className="propertiesView-sharing-title-icon">
-                        <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="white" />
+                            <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="white" />
+                        </div>
                     </div>
+                    {!this.openSharing ? (null) :
+                        <div className="propertiesView-sharing-content">
+                            {this.sharingTable}
+                        </div>}
                 </div>
-                {!this.openSharing ? (null) :
-                    <div className="propertiesView-sharing-content">
-                        {this.sharingTable}
-                    </div>}
-            </div>
 
-            {!this.isInk ? (null) :
-                <div className="propertiesView-appearance">
-                    <div className="propertiesView-appearance-title"
-                        onPointerDown={() => runInAction(() => { this.openAppearance = !this.openAppearance; })}
-                        style={{ backgroundColor: this.openAppearance ? "black" : "" }}>
-                        Appearance
+                {!this.isInk ? (null) :
+                    <div className="propertiesView-appearance">
+                        <div className="propertiesView-appearance-title"
+                            onPointerDown={() => runInAction(() => { this.openAppearance = !this.openAppearance; })}
+                            style={{ backgroundColor: this.openAppearance ? "black" : "" }}>
+                            Appearance
                         <div className="propertiesView-appearance-title-icon">
-                            <FontAwesomeIcon icon={this.openAppearance ? "caret-down" : "caret-right"} size="lg" color="white" />
+                                <FontAwesomeIcon icon={this.openAppearance ? "caret-down" : "caret-right"} size="lg" color="white" />
+                            </div>
                         </div>
-                    </div>
-                    {!this.openAppearance ? (null) :
-                        <div className="propertiesView-appearance-content">
-                            {this.appearanceEditor}
-                        </div>}
-                </div>}
+                        {!this.openAppearance ? (null) :
+                            <div className="propertiesView-appearance-content">
+                                {this.appearanceEditor}
+                            </div>}
+                    </div>}
 
-            {this.isInk ? <div className="propertiesView-transform">
-                <div className="propertiesView-transform-title"
-                    onPointerDown={() => runInAction(() => { this.openTransform = !this.openTransform; })}
-                    style={{ backgroundColor: this.openTransform ? "black" : "" }}>
-                    Transform
+                {this.isInk ? <div className="propertiesView-transform">
+                    <div className="propertiesView-transform-title"
+                        onPointerDown={() => runInAction(() => { this.openTransform = !this.openTransform; })}
+                        style={{ backgroundColor: this.openTransform ? "black" : "" }}>
+                        Transform
                     <div className="propertiesView-transform-title-icon">
-                        <FontAwesomeIcon icon={this.openTransform ? "caret-down" : "caret-right"} size="lg" color="white" />
+                            <FontAwesomeIcon icon={this.openTransform ? "caret-down" : "caret-right"} size="lg" color="white" />
+                        </div>
                     </div>
-                </div>
-                {this.openTransform ? <div className="propertiesView-transform-content">
-                    {this.transformEditor}
+                    {this.openTransform ? <div className="propertiesView-transform-content">
+                        {this.transformEditor}
+                    </div> : null}
                 </div> : null}
-            </div> : null}
-
-            <div className="propertiesView-fields">
-                <div className="propertiesView-fields-title"
-                    onPointerDown={() => runInAction(() => { this.openFields = !this.openFields; })}
-                    style={{ backgroundColor: this.openFields ? "black" : "" }}>
-                    <div className="propertiesView-fields-title-name">
-                        Fields {"&"} Tags
+
+                <div className="propertiesView-fields">
+                    <div className="propertiesView-fields-title"
+                        onPointerDown={() => runInAction(() => { this.openFields = !this.openFields; })}
+                        style={{ backgroundColor: this.openFields ? "black" : "" }}>
+                        <div className="propertiesView-fields-title-name">
+                            Fields {"&"} Tags
                         <div className="propertiesView-fields-title-icon">
-                            <FontAwesomeIcon icon={this.openFields ? "caret-down" : "caret-right"} size="lg" color="white" />
+                                <FontAwesomeIcon icon={this.openFields ? "caret-down" : "caret-right"} size="lg" color="white" />
+                            </div>
                         </div>
                     </div>
+                    {!novice && this.openFields ? <div className="propertiesView-fields-checkbox">
+                        {this.fieldsCheckbox}
+                        <div className="propertiesView-fields-checkbox-text">Layout</div>
+                    </div> : null}
+                    {!this.openFields ? (null) :
+                        <div className="propertiesView-fields-content">
+                            {novice ? this.noviceFields : this.expandedField}
+                        </div>}
                 </div>
-                {!novice && this.openFields ? <div className="propertiesView-fields-checkbox">
-                    {this.fieldsCheckbox}
-                    <div className="propertiesView-fields-checkbox-text">Layout</div>
-                </div> : null}
-                {!this.openFields ? (null) :
-                    <div className="propertiesView-fields-content">
-                        {novice ? this.noviceFields : this.expandedField}
-                    </div>}
-            </div>
-            <div className="propertiesView-layout">
-                <div className="propertiesView-layout-title"
-                    onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}
-                    style={{ backgroundColor: this.openLayout ? "black" : "" }}>
-                    Layout
+                <div className="propertiesView-layout">
+                    <div className="propertiesView-layout-title"
+                        onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}
+                        style={{ backgroundColor: this.openLayout ? "black" : "" }}>
+                        Layout
                     <div className="propertiesView-layout-title-icon" onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}>
-                        <FontAwesomeIcon icon={this.openLayout ? "caret-down" : "caret-right"} size="lg" color="white" />
+                            <FontAwesomeIcon icon={this.openLayout ? "caret-down" : "caret-right"} size="lg" color="white" />
+                        </div>
                     </div>
+                    {this.openLayout ? <div className="propertiesView-layout-content">{this.layoutPreview}</div> : null}
                 </div>
-                {this.openLayout ? <div className="propertiesView-layout-content">{this.layoutPreview}</div> : null}
-            </div>
-        </div>;
+            </div>;
+
+        }
     }
 } 
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 9248a73a6ae2adf9ddacb07396c4633178352267 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Mon, 3 Aug 2020 20:00:08 -0500
Subject: color consistencies and top menu fix for view types

---
 src/client/views/Main.scss                                         | 6 +++---
 src/client/views/PropertiesButtons.scss                            | 4 ++--
 src/client/views/collections/CollectionMenu.tsx                    | 6 ++++--
 src/client/views/collections/collectionFreeForm/PropertiesView.tsx | 2 +-
 src/client/views/nodes/DocumentView.tsx                            | 2 +-
 5 files changed, 11 insertions(+), 9 deletions(-)

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

diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss
index a2a9ceca5..97ed0a901 100644
--- a/src/client/views/Main.scss
+++ b/src/client/views/Main.scss
@@ -26,7 +26,7 @@ body {
     height: 100%;
     border-radius: inherit;
     position: inherit;
-   // background: inherit;
+    // background: inherit;
 }
 
 p {
@@ -37,7 +37,7 @@ p {
 ::-webkit-scrollbar {
     -webkit-appearance: none;
     height: 8px;
-    width:  8px;
+    width: 8px;
 }
 
 ::-webkit-scrollbar-thumb {
@@ -47,7 +47,7 @@ p {
 
 // button stuff
 button {
-    background: $dark-color;
+    background: black;
     outline: none;
     border: 0px;
     color: $light-color;
diff --git a/src/client/views/PropertiesButtons.scss b/src/client/views/PropertiesButtons.scss
index 5edaa2168..6199d34d0 100644
--- a/src/client/views/PropertiesButtons.scss
+++ b/src/client/views/PropertiesButtons.scss
@@ -77,8 +77,8 @@ $linkGap : 3px;
     color: white;
     font-size: 6px;
     width: 40px;
-    padding: 5px;
-    height: 16px;
+    padding: 3px;
+    height: 13px;
     border-radius: 7px;
     text-transform: uppercase;
     text-align: center;
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index a7d2c07fa..20df22846 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -236,7 +236,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
 
     @computed get subChrome() {
         switch (this.props.type) {
-            default:
+            default: return (null)
             case CollectionViewType.Freeform: return (<CollectionFreeFormViewChrome key="collchrome" {...this.props} isOverlay={this.props.type === CollectionViewType.Invalid} />);
             case CollectionViewType.Stacking: return (<CollectionStackingViewChrome key="collchrome" {...this.props} />);
             case CollectionViewType.Schema: return (<CollectionSchemaViewChrome key="collchrome" {...this.props} />);
@@ -586,12 +586,14 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
             </div>;
     }
 
+    @observable viewType = this.selectedDoc?._viewType;
+
     render() {
         return !this.props.docView.layoutDoc ? (null) :
             <div className="collectionFreeFormMenu-cont">
                 {this.props.docView.props.renderDepth !== 0 || this.isText ? (null) :
                     <Tooltip key="map" title={<div className="dash-tooltip">Toggle Mini Map</div>} placement="bottom">
-                        <div className="backKeyframe" onClick={this.miniMap}>
+                        <div className="backKeyframe" onClick={this.miniMap} style={{ marginRight: "5px" }}>
                             <FontAwesomeIcon icon={"map"} size={"lg"} />
                         </div>
                     </Tooltip>
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 9c5b8f81d..f04c5159c 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -238,7 +238,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                     rootSelected={returnFalse}
                     treeViewDoc={undefined}
                     backgroundColor={() => "lightgrey"}
-                    fitToBox={false}
+                    fitToBox={true}
                     FreezeDimensions={true}
                     NativeWidth={layoutDoc.type ===
                         StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : returnZero}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 81738f234..38670817b 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -749,7 +749,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         moreItems.push({ description: "Download document", icon: "download", event: async () => Doc.Zip(this.props.Document) });
         moreItems.push({ description: "Share", event: () => SharingManager.Instance.open(this), icon: "users" });
         //moreItems.push({ description: this.Document.lockedPosition ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.Document.lockedPosition) ? "unlock" : "lock" });
-        moreItems.push({ description: "Create an Alias", event: () => this.onCopy(), icon: "copy" });
+        //moreItems.push({ description: "Create an Alias", event: () => this.onCopy(), icon: "copy" });
         if (!Doc.UserDoc().noviceMode) {
             moreItems.push({ description: "Make View of Metadata Field", event: () => Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.DataDoc), icon: "concierge-bell" });
             moreItems.push({ description: `${this.Document._chromeStatus !== "disabled" ? "Hide" : "Show"} Chrome`, event: () => this.Document._chromeStatus = (this.Document._chromeStatus !== "disabled" ? "disabled" : "enabled"), icon: "project-diagram" });
-- 
cgit v1.2.3-70-g09d2


From 6ea1420c502f76a1c3219e0c34633575fb00ec98 Mon Sep 17 00:00:00 2001
From: Geireann Lindfield Roberts <60007097+geireann@users.noreply.github.com>
Date: Tue, 4 Aug 2020 18:06:29 +0800
Subject: props for prez

---
 .../collectionFreeForm/PropertiesView.tsx          | 302 +++++++--------------
 1 file changed, 95 insertions(+), 207 deletions(-)

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

diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 88d585596..3e8404874 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -27,8 +27,6 @@ import { ColorState, SketchPicker } from "react-color";
 import AntimodeMenu from "../../AntimodeMenu";
 import "./FormatShapePane.scss";
 import { discovery_v1 } from "googleapis";
-import { PresBox } from "../../nodes/PresBox";
-import { DocumentManager } from "../../../util/DocumentManager";
 
 
 interface PropertiesViewProps {
@@ -47,14 +45,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @computed get selectedDocumentView() {
         if (SelectionManager.SelectedDocuments().length) {
             return SelectionManager.SelectedDocuments()[0];
-        } else if (PresBox.Instance._selectedArray.length >= 1) {
-            return DocumentManager.Instance.getDocumentView(PresBox.Instance.rootDoc);
         } else { return undefined; }
     }
-    @computed get isPres(): boolean {
-        if (this.selectedDoc?.type === DocumentType.PRES) return true;
-        return false;
-    }
     @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; }
     @computed get dataDoc() { return this.selectedDocumentView?.dataDoc; }
 
@@ -66,13 +58,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @observable openLayout: boolean = true;
     @observable openAppearance: boolean = true;
     @observable openTransform: boolean = true;
-    //Pres Trails booleans:
-    @observable openAddSlide: boolean = true;
-    @observable openPresentationTools: boolean = true;
-    @observable openPresTransitions: boolean = true;
-    @observable openPresProgressivize: boolean = true;
-    @observable openSlideOptions: boolean = true;
-
 
     @computed get isInk() { return this.selectedDoc?.type === DocumentType.INK; }
 
@@ -220,7 +205,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         }
     }
 
-
+    @undoBatch
     setKeyValue = (value: string) => {
         if (this.selectedDoc && this.dataDoc) {
             const doc = this.layoutFields ? Doc.Layout(this.selectedDoc) : this.dataDoc;
@@ -281,9 +266,14 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         }
     }
 
+    @undoBatch
+    changePermissions = (e: any, user: string) => {
+        SharingManager.Instance.shareFromPropertiesSidebar(user, e.currentTarget.value as SharingPermissions, this.selectedDoc!);
+    }
+
     getPermissionsSelect(user: string) {
         return <select className="permissions-select"
-            onChange={e => SharingManager.Instance.shareFromPropertiesSidebar(user, e.currentTarget.value as SharingPermissions, this.selectedDoc!)}>
+            onChange={e => this.changePermissions(e, user)}>
             {Object.values(SharingPermissions).map(permission => {
                 return (
                     <option key={permission} value={permission} selected={this.selectedDoc![`ACL-${user.replace(".", "_")}`] === permission}>
@@ -359,6 +349,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         />;
     }
 
+    @undoBatch
     @action
     toggleCheckbox = () => {
         this.layoutFields = !this.layoutFields;
@@ -374,6 +365,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
             SetValue={this.setTitle} />;
     }
 
+    @undoBatch
     @action
     setTitle = (value: string) => {
         if (this.dataDoc) {
@@ -385,13 +377,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
 
-
-
-
-
-
-
-
     @undoBatch
     @action
     rotate = (angle: number) => {
@@ -726,12 +711,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     @undoBatch @action
     changeDash = () => {
-        const dash = this.dashdStk;
-        if (dash === "2") {
-            this.dashdStk = "0";
-        } else {
-            this.dashdStk = "2";
-        }
+        this.dashdStk = this.dashdStk === "2" ? "0" : "2";
     }
 
     @computed get appearanceEditor() {
@@ -753,210 +733,118 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     render() {
 
         if (!this.selectedDoc) {
-            console.log("!selectedDoc")
-            if (this.isPres === false) {
-                console.log("!isPres")
-                return <div className="propertiesView" style={{ width: this.props.width }}>
-                    <div className="propertiesView-title" style={{ width: this.props.width, paddingLeft: 6 }}>
-                        No Document Selected
-                </div> </div>;
-            }
+            return <div className="propertiesView" style={{ width: this.props.width }}>
+                <div className="propertiesView-title" style={{ width: this.props.width }}>
+                    No Document Selected
+                <div className="propertiesView-title-icon" onPointerDown={this.props.onDown}>
+                        <FontAwesomeIcon icon="times" color="black" size="xs" />
+                    </div>
+                </div>
+            </div>;
         }
 
         const novice = Doc.UserDoc().noviceMode;
 
-
-        if (this.selectedDoc && !this.isPres) {
-            return <div className="propertiesView" style={{ width: this.props.width }} >
-                <div className="propertiesView-title" style={{ width: this.props.width }}>
-                    Properties
+        return <div className="propertiesView" style={{ width: this.props.width }} >
+            <div className="propertiesView-title" style={{ width: this.props.width }}>
+                Properties
                 <div className="propertiesView-title-icon" onPointerDown={this.props.onDown}>
-                        <FontAwesomeIcon icon="times" color="black" size="sm" />
-                    </div>
-                </div>
-                <div className="propertiesView-name">
-                    {this.editableTitle}
+                    <FontAwesomeIcon icon="times" color="black" size="sm" />
                 </div>
-                <div className="propertiesView-settings">
-                    <div className="propertiesView-settings-title"
-                        onPointerDown={() => runInAction(() => { this.openActions = !this.openActions; })}
-                        style={{ backgroundColor: this.openActions ? "black" : "" }}>
-                        Actions
+            </div>
+            <div className="propertiesView-name">
+                {this.editableTitle}
+            </div>
+            <div className="propertiesView-settings">
+                <div className="propertiesView-settings-title"
+                    onPointerDown={() => runInAction(() => { this.openActions = !this.openActions; })}
+                    style={{ backgroundColor: this.openActions ? "black" : "" }}>
+                    Actions
                     <div className="propertiesView-settings-title-icon">
-                            <FontAwesomeIcon icon={this.openActions ? "caret-down" : "caret-right"} size="lg" color="white" />
-                        </div>
+                        <FontAwesomeIcon icon={this.openActions ? "caret-down" : "caret-right"} size="lg" color="white" />
                     </div>
-                    {this.openActions ? <div className="propertiesView-settings-content">
-                        <PropertiesButtons />
-                    </div> : null}
                 </div>
-                <div className="propertiesView-sharing">
-                    <div className="propertiesView-sharing-title"
-                        onPointerDown={() => runInAction(() => { this.openSharing = !this.openSharing; })}
-                        style={{ backgroundColor: this.openSharing ? "black" : "" }}>
-                        Sharing {"&"} Permissions
+                {!this.openActions ? (null) :
+                    <div className="propertiesView-settings-content">
+                        <PropertiesButtons />
+                    </div>}
+            </div>
+            <div className="propertiesView-sharing">
+                <div className="propertiesView-sharing-title"
+                    onPointerDown={() => runInAction(() => { this.openSharing = !this.openSharing; })}
+                    style={{ backgroundColor: this.openSharing ? "black" : "" }}>
+                    Sharing {"&"} Permissions
                     <div className="propertiesView-sharing-title-icon">
-                            <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="white" />
-                        </div>
+                        <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="white" />
                     </div>
-                    {this.openSharing ? <div className="propertiesView-sharing-content">
-                        {this.sharingTable}
-                    </div> : null}
                 </div>
+                {!this.openSharing ? (null) :
+                    <div className="propertiesView-sharing-content">
+                        {this.sharingTable}
+                    </div>}
+            </div>
 
-
-
-
-                {this.isInk ? <div className="propertiesView-appearance">
+            {!this.isInk ? (null) :
+                <div className="propertiesView-appearance">
                     <div className="propertiesView-appearance-title"
                         onPointerDown={() => runInAction(() => { this.openAppearance = !this.openAppearance; })}
                         style={{ backgroundColor: this.openAppearance ? "black" : "" }}>
                         Appearance
-                    <div className="propertiesView-appearance-title-icon">
+                        <div className="propertiesView-appearance-title-icon">
                             <FontAwesomeIcon icon={this.openAppearance ? "caret-down" : "caret-right"} size="lg" color="white" />
                         </div>
                     </div>
-                    {this.openAppearance ? <div className="propertiesView-appearance-content">
-                        {this.appearanceEditor}
-                    </div> : null}
-                </div> : null}
-
-                {this.isInk ? <div className="propertiesView-transform">
-                    <div className="propertiesView-transform-title"
-                        onPointerDown={() => runInAction(() => { this.openTransform = !this.openTransform; })}
-                        style={{ backgroundColor: this.openTransform ? "black" : "" }}>
-                        Transform
+                    {!this.openAppearance ? (null) :
+                        <div className="propertiesView-appearance-content">
+                            {this.appearanceEditor}
+                        </div>}
+                </div>}
+
+            {this.isInk ? <div className="propertiesView-transform">
+                <div className="propertiesView-transform-title"
+                    onPointerDown={() => runInAction(() => { this.openTransform = !this.openTransform; })}
+                    style={{ backgroundColor: this.openTransform ? "black" : "" }}>
+                    Transform
                     <div className="propertiesView-transform-title-icon">
-                            <FontAwesomeIcon icon={this.openTransform ? "caret-down" : "caret-right"} size="lg" color="white" />
-                        </div>
+                        <FontAwesomeIcon icon={this.openTransform ? "caret-down" : "caret-right"} size="lg" color="white" />
                     </div>
-                    {this.openTransform ? <div className="propertiesView-transform-content">
-                        {this.transformEditor}
-                    </div> : null}
+                </div>
+                {this.openTransform ? <div className="propertiesView-transform-content">
+                    {this.transformEditor}
                 </div> : null}
-
-
-
-
-
-                <div className="propertiesView-fields">
-                    <div className="propertiesView-fields-title"
-                        onPointerDown={() => runInAction(() => { this.openFields = !this.openFields; })}
-                        style={{ backgroundColor: this.openFields ? "black" : "" }}>
-                        <div className="propertiesView-fields-title-name">
-                            Fields {"&"} Tags
+            </div> : null}
+
+            <div className="propertiesView-fields">
+                <div className="propertiesView-fields-title"
+                    onPointerDown={() => runInAction(() => { this.openFields = !this.openFields; })}
+                    style={{ backgroundColor: this.openFields ? "black" : "" }}>
+                    <div className="propertiesView-fields-title-name">
+                        Fields {"&"} Tags
                         <div className="propertiesView-fields-title-icon">
-                                <FontAwesomeIcon icon={this.openFields ? "caret-down" : "caret-right"} size="lg" color="white" />
-                            </div>
-                        </div>
-                    </div>
-                    {!novice && this.openFields ? <div className="propertiesView-fields-checkbox">
-                        {this.fieldsCheckbox}
-                        <div className="propertiesView-fields-checkbox-text">Layout</div>
-                    </div> : null}
-                    {this.openFields ?
-                        <div className="propertiesView-fields-content">
-                            {novice ? this.noviceFields : this.expandedField}
-                        </div> : null}
-                </div>
-                <div className="propertiesView-layout">
-                    <div className="propertiesView-layout-title"
-                        onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}
-                        style={{ backgroundColor: this.openLayout ? "black" : "" }}>
-                        Layout
-                    <div className="propertiesView-layout-title-icon"
-                            onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}>
-                            <FontAwesomeIcon icon={this.openLayout ? "caret-down" : "caret-right"} size="lg" color="white" />
-                        </div>
-                    </div>
-                    {this.openLayout ? <div className="propertiesView-layout-content">{this.layoutPreview}</div> : null}
-                </div>
-            </div>;
-        }
-
-        if (this.isPres) {
-            return <div className="propertiesView" style={{ width: this.props.width }} >
-                <div className="propertiesView-title" style={{ width: this.props.width }}>
-                    Presentation Toolbar
-                <div className="propertiesView-title-icon" onPointerDown={this.props.onDown}>
-                        <FontAwesomeIcon icon="times" color="black" size="sm" />
-                    </div>
-                </div>
-                <div className="propertiesView-name">
-                    {this.editableTitle}
-                    <div className="propertiesView-presSelected">
-                        {PresBox.Instance._selectedArray.length} selected
-                        <div className="propertiesView-selectedList">
-                            {PresBox.Instance.listOfSelected}
-                        </div>
-                    </div>
-                </div>
-                <div className="propertiesView-settings">
-                    <div className="propertiesView-settings-title"
-                        onPointerDown={() => runInAction(() => { this.openAddSlide = !this.openAddSlide; })}
-                        style={{ backgroundColor: this.openAddSlide ? "black" : "" }}>
-                        &nbsp; <FontAwesomeIcon icon={"plus"} /> &nbsp; Add new slide
-                    <div className="propertiesView-settings-title-icon">
-                            <FontAwesomeIcon icon={this.openAddSlide ? "caret-down" : "caret-right"} size="lg" color="white" />
-                        </div>
-                    </div>
-                    {this.openAddSlide ? <div className="propertiesView-settings-content">
-                        {PresBox.Instance.newDocumentDropdown}
-                    </div> : null}
-                </div>
-                <div className="propertiesView-sharing">
-                    <div className="propertiesView-sharing-title"
-                        onPointerDown={() => runInAction(() => { this.openPresTransitions = !this.openPresTransitions; })}
-                        style={{ backgroundColor: this.openPresTransitions ? "black" : "" }}>
-                        &nbsp; <FontAwesomeIcon icon={"rocket"} /> &nbsp; Transitions
-                    <div className="propertiesView-sharing-title-icon">
-                            <FontAwesomeIcon icon={this.openPresTransitions ? "caret-down" : "caret-right"} size="lg" color="white" />
-                        </div>
-                    </div>
-                    {this.openPresTransitions ? <div className="propertiesView-sharing-content">
-                        {PresBox.Instance.transitionDropdown}
-                    </div> : null}
-                </div>
-                <div className="propertiesView-sharing">
-                    <div className="propertiesView-sharing-title"
-                        onPointerDown={() => runInAction(() => { this.openPresProgressivize = !this.openPresProgressivize; })}
-                        style={{ backgroundColor: this.openPresProgressivize ? "black" : "" }}>
-                        &nbsp; <FontAwesomeIcon icon={"tasks"} /> &nbsp; Progressivize
-                    <div className="propertiesView-sharing-title-icon">
-                            <FontAwesomeIcon icon={this.openPresProgressivize ? "caret-down" : "caret-right"} size="lg" color="white" />
-                        </div>
-                    </div>
-                    {this.openPresProgressivize ? <div className="propertiesView-sharing-content">
-                        {PresBox.Instance.progressivizeDropdown}
-                    </div> : null}
-                </div>
-                <div className="propertiesView-sharing">
-                    <div className="propertiesView-sharing-title"
-                        onPointerDown={() => runInAction(() => { this.openSlideOptions = !this.openSlideOptions; })}
-                        style={{ backgroundColor: this.openSlideOptions ? "black" : "" }}>
-                        <FontAwesomeIcon icon={"cog"} /> &nbsp; Slide options
-                    <div className="propertiesView-sharing-title-icon">
-                            <FontAwesomeIcon icon={this.openSlideOptions ? "caret-down" : "caret-right"} size="lg" color="white" />
+                            <FontAwesomeIcon icon={this.openFields ? "caret-down" : "caret-right"} size="lg" color="white" />
                         </div>
                     </div>
-                    {this.openSlideOptions ? <div className="propertiesView-sharing-content">
-                        {PresBox.Instance.optionsDropdown}
-                    </div> : null}
                 </div>
-                <div className="propertiesView-sharing">
-                    <div className="propertiesView-sharing-title"
-                        onPointerDown={() => runInAction(() => { this.openSharing = !this.openSharing; })}
-                        style={{ backgroundColor: this.openSharing ? "black" : "" }}>
-                        Sharing {"&"} Permissions
-                    <div className="propertiesView-sharing-title-icon">
-                            <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="white" />
-                        </div>
+                {!novice && this.openFields ? <div className="propertiesView-fields-checkbox">
+                    {this.fieldsCheckbox}
+                    <div className="propertiesView-fields-checkbox-text">Layout</div>
+                </div> : null}
+                {!this.openFields ? (null) :
+                    <div className="propertiesView-fields-content">
+                        {novice ? this.noviceFields : this.expandedField}
+                    </div>}
+            </div>
+            <div className="propertiesView-layout">
+                <div className="propertiesView-layout-title"
+                    onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}
+                    style={{ backgroundColor: this.openLayout ? "black" : "" }}>
+                    Layout
+                    <div className="propertiesView-layout-title-icon" onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}>
+                        <FontAwesomeIcon icon={this.openLayout ? "caret-down" : "caret-right"} size="lg" color="white" />
                     </div>
-                    {this.openSharing ? <div className="propertiesView-sharing-content">
-                        {this.sharingTable}
-                    </div> : null}
                 </div>
-            </div>;
-        }
+                {this.openLayout ? <div className="propertiesView-layout-content">{this.layoutPreview}</div> : null}
+            </div>
+        </div>;
     }
-} 
\ No newline at end of file
+}
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 917deb0c0d73997f4ffa465e75ac05fdca7a8519 Mon Sep 17 00:00:00 2001
From: Geireann Lindfield Roberts <60007097+geireann@users.noreply.github.com>
Date: Wed, 5 Aug 2020 01:21:44 +0800
Subject: pres elements

---
 .../collectionFreeForm/PropertiesView.tsx          | 260 ++++++++----
 src/client/views/nodes/AudioBox.tsx                |   9 +-
 src/client/views/nodes/PresBox.scss                |   1 +
 src/client/views/nodes/PresBox.tsx                 | 445 ++++++++-------------
 .../views/presentationview/PresElementBox.tsx      |  17 +-
 5 files changed, 365 insertions(+), 367 deletions(-)

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

diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 3e8404874..1f66d4144 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -27,6 +27,8 @@ import { ColorState, SketchPicker } from "react-color";
 import AntimodeMenu from "../../AntimodeMenu";
 import "./FormatShapePane.scss";
 import { discovery_v1 } from "googleapis";
+import { PresBox } from "../../nodes/PresBox";
+import { DocumentManager } from "../../../util/DocumentManager";
 
 
 interface PropertiesViewProps {
@@ -45,8 +47,14 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @computed get selectedDocumentView() {
         if (SelectionManager.SelectedDocuments().length) {
             return SelectionManager.SelectedDocuments()[0];
+        } else if (PresBox.Instance._selectedArray.length >= 1) {
+            return DocumentManager.Instance.getDocumentView(PresBox.Instance.rootDoc);
         } else { return undefined; }
     }
+    @computed get isPres(): boolean {
+        if (this.selectedDoc?.type === DocumentType.PRES) return true;
+        return false;
+    }
     @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; }
     @computed get dataDoc() { return this.selectedDocumentView?.dataDoc; }
 
@@ -58,6 +66,12 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @observable openLayout: boolean = true;
     @observable openAppearance: boolean = true;
     @observable openTransform: boolean = true;
+    //Pres Trails booleans:
+    @observable openAddSlide: boolean = true;
+    @observable openPresentationTools: boolean = true;
+    @observable openPresTransitions: boolean = true;
+    @observable openPresProgressivize: boolean = true;
+    @observable openSlideOptions: boolean = true;
 
     @computed get isInk() { return this.selectedDoc?.type === DocumentType.INK; }
 
@@ -732,7 +746,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     render() {
 
-        if (!this.selectedDoc) {
+        if (!this.selectedDoc && !this.isPres) {
             return <div className="propertiesView" style={{ width: this.props.width }}>
                 <div className="propertiesView-title" style={{ width: this.props.width }}>
                     No Document Selected
@@ -745,106 +759,192 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
         const novice = Doc.UserDoc().noviceMode;
 
-        return <div className="propertiesView" style={{ width: this.props.width }} >
-            <div className="propertiesView-title" style={{ width: this.props.width }}>
-                Properties
+        if (this.selectedDoc && !this.isPres) {
+            return <div className="propertiesView" style={{ width: this.props.width }} >
+                <div className="propertiesView-title" style={{ width: this.props.width }}>
+                    Properties
                 <div className="propertiesView-title-icon" onPointerDown={this.props.onDown}>
-                    <FontAwesomeIcon icon="times" color="black" size="sm" />
+                        <FontAwesomeIcon icon="times" color="black" size="sm" />
+                    </div>
                 </div>
-            </div>
-            <div className="propertiesView-name">
-                {this.editableTitle}
-            </div>
-            <div className="propertiesView-settings">
-                <div className="propertiesView-settings-title"
-                    onPointerDown={() => runInAction(() => { this.openActions = !this.openActions; })}
-                    style={{ backgroundColor: this.openActions ? "black" : "" }}>
-                    Actions
+                <div className="propertiesView-name">
+                    {this.editableTitle}
+                </div>
+                <div className="propertiesView-settings">
+                    <div className="propertiesView-settings-title"
+                        onPointerDown={() => runInAction(() => { this.openActions = !this.openActions; })}
+                        style={{ backgroundColor: this.openActions ? "black" : "" }}>
+                        Actions
                     <div className="propertiesView-settings-title-icon">
-                        <FontAwesomeIcon icon={this.openActions ? "caret-down" : "caret-right"} size="lg" color="white" />
+                            <FontAwesomeIcon icon={this.openActions ? "caret-down" : "caret-right"} size="lg" color="white" />
+                        </div>
                     </div>
+                    {!this.openActions ? (null) :
+                        <div className="propertiesView-settings-content">
+                            <PropertiesButtons />
+                        </div>}
                 </div>
-                {!this.openActions ? (null) :
-                    <div className="propertiesView-settings-content">
-                        <PropertiesButtons />
-                    </div>}
-            </div>
-            <div className="propertiesView-sharing">
-                <div className="propertiesView-sharing-title"
-                    onPointerDown={() => runInAction(() => { this.openSharing = !this.openSharing; })}
-                    style={{ backgroundColor: this.openSharing ? "black" : "" }}>
-                    Sharing {"&"} Permissions
+                <div className="propertiesView-sharing">
+                    <div className="propertiesView-sharing-title"
+                        onPointerDown={() => runInAction(() => { this.openSharing = !this.openSharing; })}
+                        style={{ backgroundColor: this.openSharing ? "black" : "" }}>
+                        Sharing {"&"} Permissions
                     <div className="propertiesView-sharing-title-icon">
-                        <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="white" />
+                            <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="white" />
+                        </div>
                     </div>
+                    {!this.openSharing ? (null) :
+                        <div className="propertiesView-sharing-content">
+                            {this.sharingTable}
+                        </div>}
                 </div>
-                {!this.openSharing ? (null) :
-                    <div className="propertiesView-sharing-content">
-                        {this.sharingTable}
-                    </div>}
-            </div>
 
-            {!this.isInk ? (null) :
-                <div className="propertiesView-appearance">
-                    <div className="propertiesView-appearance-title"
-                        onPointerDown={() => runInAction(() => { this.openAppearance = !this.openAppearance; })}
-                        style={{ backgroundColor: this.openAppearance ? "black" : "" }}>
-                        Appearance
+                {!this.isInk ? (null) :
+                    <div className="propertiesView-appearance">
+                        <div className="propertiesView-appearance-title"
+                            onPointerDown={() => runInAction(() => { this.openAppearance = !this.openAppearance; })}
+                            style={{ backgroundColor: this.openAppearance ? "black" : "" }}>
+                            Appearance
                         <div className="propertiesView-appearance-title-icon">
-                            <FontAwesomeIcon icon={this.openAppearance ? "caret-down" : "caret-right"} size="lg" color="white" />
+                                <FontAwesomeIcon icon={this.openAppearance ? "caret-down" : "caret-right"} size="lg" color="white" />
+                            </div>
                         </div>
-                    </div>
-                    {!this.openAppearance ? (null) :
-                        <div className="propertiesView-appearance-content">
-                            {this.appearanceEditor}
-                        </div>}
-                </div>}
+                        {!this.openAppearance ? (null) :
+                            <div className="propertiesView-appearance-content">
+                                {this.appearanceEditor}
+                            </div>}
+                    </div>}
 
-            {this.isInk ? <div className="propertiesView-transform">
-                <div className="propertiesView-transform-title"
-                    onPointerDown={() => runInAction(() => { this.openTransform = !this.openTransform; })}
-                    style={{ backgroundColor: this.openTransform ? "black" : "" }}>
-                    Transform
+                {this.isInk ? <div className="propertiesView-transform">
+                    <div className="propertiesView-transform-title"
+                        onPointerDown={() => runInAction(() => { this.openTransform = !this.openTransform; })}
+                        style={{ backgroundColor: this.openTransform ? "black" : "" }}>
+                        Transform
                     <div className="propertiesView-transform-title-icon">
-                        <FontAwesomeIcon icon={this.openTransform ? "caret-down" : "caret-right"} size="lg" color="white" />
+                            <FontAwesomeIcon icon={this.openTransform ? "caret-down" : "caret-right"} size="lg" color="white" />
+                        </div>
                     </div>
-                </div>
-                {this.openTransform ? <div className="propertiesView-transform-content">
-                    {this.transformEditor}
+                    {this.openTransform ? <div className="propertiesView-transform-content">
+                        {this.transformEditor}
+                    </div> : null}
                 </div> : null}
-            </div> : null}
-
-            <div className="propertiesView-fields">
-                <div className="propertiesView-fields-title"
-                    onPointerDown={() => runInAction(() => { this.openFields = !this.openFields; })}
-                    style={{ backgroundColor: this.openFields ? "black" : "" }}>
-                    <div className="propertiesView-fields-title-name">
-                        Fields {"&"} Tags
+
+                <div className="propertiesView-fields">
+                    <div className="propertiesView-fields-title"
+                        onPointerDown={() => runInAction(() => { this.openFields = !this.openFields; })}
+                        style={{ backgroundColor: this.openFields ? "black" : "" }}>
+                        <div className="propertiesView-fields-title-name">
+                            Fields {"&"} Tags
                         <div className="propertiesView-fields-title-icon">
-                            <FontAwesomeIcon icon={this.openFields ? "caret-down" : "caret-right"} size="lg" color="white" />
+                                <FontAwesomeIcon icon={this.openFields ? "caret-down" : "caret-right"} size="lg" color="white" />
+                            </div>
                         </div>
                     </div>
+                    {!novice && this.openFields ? <div className="propertiesView-fields-checkbox">
+                        {this.fieldsCheckbox}
+                        <div className="propertiesView-fields-checkbox-text">Layout</div>
+                    </div> : null}
+                    {!this.openFields ? (null) :
+                        <div className="propertiesView-fields-content">
+                            {novice ? this.noviceFields : this.expandedField}
+                        </div>}
                 </div>
-                {!novice && this.openFields ? <div className="propertiesView-fields-checkbox">
-                    {this.fieldsCheckbox}
-                    <div className="propertiesView-fields-checkbox-text">Layout</div>
-                </div> : null}
-                {!this.openFields ? (null) :
-                    <div className="propertiesView-fields-content">
-                        {novice ? this.noviceFields : this.expandedField}
-                    </div>}
-            </div>
-            <div className="propertiesView-layout">
-                <div className="propertiesView-layout-title"
-                    onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}
-                    style={{ backgroundColor: this.openLayout ? "black" : "" }}>
-                    Layout
+                <div className="propertiesView-layout">
+                    <div className="propertiesView-layout-title"
+                        onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}
+                        style={{ backgroundColor: this.openLayout ? "black" : "" }}>
+                        Layout
                     <div className="propertiesView-layout-title-icon" onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}>
-                        <FontAwesomeIcon icon={this.openLayout ? "caret-down" : "caret-right"} size="lg" color="white" />
+                            <FontAwesomeIcon icon={this.openLayout ? "caret-down" : "caret-right"} size="lg" color="white" />
+                        </div>
                     </div>
+                    {this.openLayout ? <div className="propertiesView-layout-content">{this.layoutPreview}</div> : null}
                 </div>
-                {this.openLayout ? <div className="propertiesView-layout-content">{this.layoutPreview}</div> : null}
-            </div>
-        </div>;
+            </div>;
+        }
+        if (this.isPres) {
+            return <div className="propertiesView" style={{ width: this.props.width }} >
+                <div className="propertiesView-title" style={{ width: this.props.width }}>
+                    Presentation Toolbar
+                <div className="propertiesView-title-icon" onPointerDown={this.props.onDown}>
+                        <FontAwesomeIcon icon="times" color="black" size="sm" />
+                    </div>
+                </div>
+                <div className="propertiesView-name">
+                    {this.editableTitle}
+                    <div className="propertiesView-presSelected">
+                        {PresBox.Instance._selectedArray.length} selected
+                        <div className="propertiesView-selectedList">
+                            {PresBox.Instance.listOfSelected}
+                        </div>
+                    </div>
+                </div>
+                <div className="propertiesView-settings">
+                    <div className="propertiesView-settings-title"
+                        onPointerDown={() => runInAction(() => { this.openAddSlide = !this.openAddSlide; })}
+                        style={{ backgroundColor: this.openAddSlide ? "black" : "" }}>
+                        &nbsp; <FontAwesomeIcon icon={"plus"} /> &nbsp; Add new slide
+                    <div className="propertiesView-settings-title-icon">
+                            <FontAwesomeIcon icon={this.openAddSlide ? "caret-down" : "caret-right"} size="lg" color="white" />
+                        </div>
+                    </div>
+                    {this.openAddSlide ? <div className="propertiesView-settings-content">
+                        {PresBox.Instance.newDocumentDropdown}
+                    </div> : null}
+                </div>
+                <div className="propertiesView-sharing">
+                    <div className="propertiesView-sharing-title"
+                        onPointerDown={() => runInAction(() => { this.openPresTransitions = !this.openPresTransitions; })}
+                        style={{ backgroundColor: this.openPresTransitions ? "black" : "" }}>
+                        &nbsp; <FontAwesomeIcon icon={"rocket"} /> &nbsp; Transitions
+                    <div className="propertiesView-sharing-title-icon">
+                            <FontAwesomeIcon icon={this.openPresTransitions ? "caret-down" : "caret-right"} size="lg" color="white" />
+                        </div>
+                    </div>
+                    {this.openPresTransitions ? <div className="propertiesView-sharing-content">
+                        {PresBox.Instance.transitionDropdown}
+                    </div> : null}
+                </div>
+                <div className="propertiesView-sharing">
+                    <div className="propertiesView-sharing-title"
+                        onPointerDown={() => runInAction(() => { this.openPresProgressivize = !this.openPresProgressivize; })}
+                        style={{ backgroundColor: this.openPresProgressivize ? "black" : "" }}>
+                        &nbsp; <FontAwesomeIcon icon={"tasks"} /> &nbsp; Progressivize
+                    <div className="propertiesView-sharing-title-icon">
+                            <FontAwesomeIcon icon={this.openPresProgressivize ? "caret-down" : "caret-right"} size="lg" color="white" />
+                        </div>
+                    </div>
+                    {this.openPresProgressivize ? <div className="propertiesView-sharing-content">
+                        {PresBox.Instance.progressivizeDropdown}
+                    </div> : null}
+                </div>
+                <div className="propertiesView-sharing">
+                    <div className="propertiesView-sharing-title"
+                        onPointerDown={() => runInAction(() => { this.openSlideOptions = !this.openSlideOptions; })}
+                        style={{ backgroundColor: this.openSlideOptions ? "black" : "" }}>
+                        <FontAwesomeIcon icon={"cog"} /> &nbsp; {PresBox.Instance.stringType} options
+                    <div className="propertiesView-sharing-title-icon">
+                            <FontAwesomeIcon icon={this.openSlideOptions ? "caret-down" : "caret-right"} size="lg" color="white" />
+                        </div>
+                    </div>
+                    {this.openSlideOptions ? <div className="propertiesView-sharing-content">
+                        {PresBox.Instance.optionsDropdown}
+                    </div> : null}
+                </div>
+                <div className="propertiesView-sharing">
+                    <div className="propertiesView-sharing-title"
+                        onPointerDown={() => runInAction(() => { this.openSharing = !this.openSharing; })}
+                        style={{ backgroundColor: this.openSharing ? "black" : "" }}>
+                        Sharing {"&"} Permissions
+                    <div className="propertiesView-sharing-title-icon">
+                            <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="white" />
+                        </div>
+                    </div>
+                    {this.openSharing ? <div className="propertiesView-sharing-content">
+                        {this.sharingTable}
+                    </div> : null}
+                </div>
+            </div>;
+        }
     }
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 5c921cea4..dba92faae 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -21,6 +21,7 @@ import { Docs, DocUtils } from "../../documents/Documents";
 import { ComputedField } from "../../../fields/ScriptField";
 import { Networking } from "../../Network";
 import { LinkAnchorBox } from "./LinkAnchorBox";
+import { signedCookie } from "cookie-parser";
 
 // testing testing 
 
@@ -43,7 +44,7 @@ const AudioDocument = makeInterface(documentSchema, audioSchema);
 export class AudioBox extends ViewBoxBaseComponent<FieldViewProps, AudioDocument>(AudioDocument) {
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(AudioBox, fieldKey); }
     public static Enabled = false;
-
+    static Instance: AudioBox;
     _linkPlayDisposer: IReactionDisposer | undefined;
     _reactionDisposer: IReactionDisposer | undefined;
     _scrubbingDisposer: IReactionDisposer | undefined;
@@ -51,12 +52,14 @@ export class AudioBox extends ViewBoxBaseComponent<FieldViewProps, AudioDocument
     _recorder: any;
     _recordStart = 0;
     _stream: MediaStream | undefined;
-
+    constructor(props: any) {
+        super(props);
+        AudioBox.Instance = this;
+    }
     @observable private static _scrubTime = 0;
     @computed get audioState(): undefined | "recording" | "paused" | "playing" { return this.dataDoc.audioState as (undefined | "recording" | "paused" | "playing"); }
     set audioState(value) { this.dataDoc.audioState = value; }
     public static SetScrubTime = (timeInMillisFrom1970: number) => { runInAction(() => AudioBox._scrubTime = 0); runInAction(() => AudioBox._scrubTime = timeInMillisFrom1970); };
-
     @computed get recordingStart() { return Cast(this.dataDoc[this.props.fieldKey + "-recordingStart"], DateField)?.date.getTime(); }
     async slideTemplate() { return (await Cast((await Cast(Doc.UserDoc().slidesBtn, Doc) as Doc).dragFactory, Doc) as Doc); }
 
diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss
index 45c6d33b8..089f69873 100644
--- a/src/client/views/nodes/PresBox.scss
+++ b/src/client/views/nodes/PresBox.scss
@@ -667,6 +667,7 @@
         height: 55px;
         min-width: 90px;
         width: 90px;
+        overflow: hidden;
         background-color: white;
         border: solid darkgrey 1px;
         display: grid;
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index 0a73106a3..2389d3875 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -33,6 +33,7 @@ import { translate } from "googleapis/build/src/apis/translate";
 import { DragManager, dropActionType } from "../../util/DragManager";
 import { actionAsync } from "mobx-utils";
 import { SelectionManager } from "../../util/SelectionManager";
+import { AudioBox } from "./AudioBox";
 
 type PresBoxSchema = makeInterface<[typeof documentSchema]>;
 const PresBoxDocument = makeInterface(documentSchema);
@@ -90,6 +91,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         Doc.UserDoc().activePresentation = this.rootDoc;
     }
 
+    @observable _moveOnFromAudio: boolean = false;
+
     @undoBatch
     @action
     next = () => {
@@ -106,9 +109,18 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
             presTargetDoc.currentFrame = curFrame + 1;
             if (presTargetDoc.zoomProgressivize) this.zoomProgressivizeNext(presTargetDoc);
             // Case 2: No more frames in current doc and next slide is defined, therefore move to next slide
+        } else if ((presTargetDoc.type === DocumentType.VID || presTargetDoc.type === DocumentType.AUDIO) && !this._moveOnFromAudio) {
+            if (presTargetDoc.type === DocumentType.AUDIO) {
+                AudioBox.Instance.playFrom(0);
+                this._moveOnFromAudio = true;
+            }
+            if (presTargetDoc.type === DocumentType.VID) {
+                this._moveOnFromAudio = true;
+            }
         } else if (this.childDocs[this.itemIndex + 1] !== undefined) {
             const nextSelected = this.itemIndex + 1;
             this.gotoDocument(nextSelected, this.itemIndex);
+            this._moveOnFromAudio = false;
         }
     }
 
@@ -185,73 +197,100 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
 
 
     @action
-    onHideDocumentUntilPressClick = () => {
+    onHideDocument = () => {
         this.childDocs.forEach((doc, index) => {
             const curDoc = Cast(doc, Doc, null);
             const tagDoc = Cast(curDoc.presentationTargetDoc, Doc, null);
-            if (tagDoc.presEffect === 'None' || !tagDoc.presEffect) {
-                tagDoc.opacity = 1;
-            } else {
-                if (index <= this.itemIndex) {
+            if (tagDoc) tagDoc.opacity = 1;
+            if (curDoc.presHideTillShownButton) {
+                console.log("-------------hide before---------------");
+                console.log("this.itemIndex: " + this.itemIndex);
+                console.log("index: " + index)
+                if (index > this.itemIndex) {
+                    tagDoc.opacity = 0;
+                } else if (!curDoc.presHideAfterButton) {
                     tagDoc.opacity = 1;
-                } else {
+                }
+            }
+            if (curDoc.presHideAfterButton) {
+                console.log("-------------hide after---------------");
+                console.log("this.itemIndex: " + (this.itemIndex + 1));
+                console.log("index: " + (index + 1))
+                if (index < this.itemIndex) {
                     tagDoc.opacity = 0;
+                } else if (!curDoc.presHideTillShownButton) {
+                    tagDoc.opacity = 1;
                 }
             }
         });
     }
 
-    /**
-     * This is the method that checks for the actions that need to be performed
-     * before the document has been presented, which involves 3 button options:
-     * Hide Until Presented, Hide After Presented, Fade After Presented
-     */
     @action
-    hideDocumentInPres = () => {
-        this.updateCurrentPresentation();
-        this.childDocs.forEach((doc, i) => {
-            const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
-            console.log("HB: " + doc.presHideTillShownButton);
-            console.log("HA: " + doc.presHideAfterButton);
-            if (doc.presHideTillShownButton) {
-                if (i < this.itemIndex) {
-                    console.log(i + 1 + "hide before");
-                    tagDoc.opacity = 0;
-                    console.log(tagDoc.opacity);
-                } else {
-                    tagDoc.opacity = 1;
-                }
-            }
-            if (doc.presHideAfterButton) {
-                if (i > this.itemIndex) {
-                    console.log(i + 1 + "hide after");
+    onHideAfterPresClick = () => {
+        this.childDocs.forEach((doc, index) => {
+            const curDoc = Cast(doc, Doc, null);
+            const tagDoc = Cast(curDoc.presentationTargetDoc, Doc, null);
+            if (curDoc.presHideAfterButton) {
+                if (index < this.itemIndex) {
                     tagDoc.opacity = 0;
-                    console.log(tagDoc.opacity);
-                } else {
+                } else if (index = this.itemIndex) {
                     tagDoc.opacity = 1;
                 }
             }
         });
     }
 
+    /**
+     * This is the method that checks for the actions that need to be performed
+     * before the document has been presented, which involves 3 button options:
+     * Hide Until Presented, Hide After Presented, Fade After Presented
+     */
+    // @action
+    // hideDocumentInPres = () => {
+    //     this.updateCurrentPresentation();
+    //     this.childDocs.forEach((doc, i) => {
+    //         const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
+    //         console.log("HB: " + doc.presHideTillShownButton);
+    //         console.log("HA: " + doc.presHideAfterButton);
+    //         if (doc.presHideTillShownButton) {
+    //             if (i < this.itemIndex) {
+    //                 console.log(i + 1 + "hide before");
+    //                 tagDoc.opacity = 0;
+    //                 console.log(tagDoc.opacity);
+    //             } else {
+    //                 tagDoc.opacity = 1;
+    //             }
+    //         }
+    //         if (doc.presHideAfterButton) {
+    //             if (i > this.itemIndex) {
+    //                 console.log(i + 1 + "hide after");
+    //                 tagDoc.opacity = 0;
+    //                 console.log(tagDoc.opacity);
+    //             } else {
+    //                 tagDoc.opacity = 1;
+    //             }
+    //         }
+    //     });
+    // }
+
     /**
      * This is the method that checks for the actions that need to be performed
      * after the document has been presented, which involves 3 button options:
      * Hide Until Presented, Hide After Presented, Fade After Presented
      */
-    showAfterPresented = (index: number) => {
-        this.updateCurrentPresentation();
-        this.childDocs.forEach((doc, ind) => {
-            const presTargetDoc = doc.presentationTargetDoc as Doc;
-            //the order of cases is aligned based on priority
-            if (doc.presHideTillShownButton && ind <= index) {
-                presTargetDoc.opacity = 1;
-            }
-            if (doc.presHideAfterButton && ind < index) {
-                presTargetDoc.opacity = 0;
-            }
-        });
-    }
+    // showAfterPresented = (index: number) => {
+    //     this.updateCurrentPresentation();
+    //     this.childDocs.forEach((doc, ind) => {
+    //         const presTargetDoc = doc.presentationTargetDoc as Doc;
+    //         //the order of cases is aligned based on priority
+    //         if (doc.presHideTillShownButton && ind <= index) {
+    //             presTargetDoc.opacity = 1;
+    //         }
+    //         if (doc.presHideAfterButton && ind < index) {
+    //             presTargetDoc.opacity = 0;
+    //         }
+    //     });
+    // }
 
     /**
      * This method makes sure that cursor navigates to the element that
@@ -264,6 +303,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         const srcContext = await DocCastAsync(targetDoc.context);
         const presCollection = Cast(this.layoutDoc.presCollection, Doc, null);
         const collectionDocView = presCollection ? await DocumentManager.Instance.getDocumentView(presCollection) : undefined;
+        this.turnOffEdit();
+
         if (this.itemIndex >= 0) {
             if (targetDoc) {
                 if (srcContext) this.layoutDoc.presCollection = srcContext;
@@ -272,12 +313,21 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         if (srcContext) console.log("NC: " + srcContext.title);
         if (presCollection) console.log("PC: " + presCollection.title);
         if (collectionDocView) {
-            if (srcContext && srcContext !== presCollection) {
-                console.log("Case 1: new srcContext inside of current collection so add a new tab to the current pres collection");
-                console.log(collectionDocView);
-                collectionDocView.props.addDocTab(srcContext, "inPlace");
+            if (activeItem.openDocument) {
+                collectionDocView.props.addDocTab(activeItem, "inPlace");
+            } else if (srcContext && srcContext !== presCollection) {
+                if (activeItem.openDocument) {
+                    collectionDocView.props.addDocTab(activeItem, "inPlace");
+                } else {
+                    console.log("Case 1: new srcContext inside of current collection so add a new tab to the current pres collection");
+                    console.log(collectionDocView);
+                    collectionDocView.props.addDocTab(srcContext, "inPlace");
+                }
             }
         }
+        if (targetDoc.presWebsiteData) {
+            targetDoc.data = targetDoc.presWebsiteData;
+        }
         // else if (srcContext) {
         //     console.log("Case 2: srcContext - not open and collection containing this document exists, so open collection that contains it and then await zooming in on document");
         //     this.props.addDocTab(srcContext, "onRight");
@@ -290,7 +340,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         const willZoom = false;
 
         //docToJump stayed same meaning, it was not in the group or was the last element in the group
-        if (docToJump === curDoc) {
+        if (targetDoc.zoomProgressivize && this.rootDoc.presStatus !== 'edit') {
+            this.zoomProgressivizeNext(targetDoc);
+        } else if (docToJump === curDoc) {
             //checking if curDoc has navigation open
             if (curDoc.presNavButton && targetDoc) {
                 await DocumentManager.Instance.jumpToDocument(targetDoc, false, undefined, srcContext);
@@ -320,7 +372,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
             // this.hideIfNotPresented(index);
             // this.showAfterPresented(index);
             // this.hideDocumentInPres();
-            this.onHideDocumentUntilPressClick();
+            this.onHideDocument();
+            // this.onHideAfterPresClick();
         }
     });
 
@@ -371,14 +424,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
             if (doc.presHideAfterButton && this.childDocs.indexOf(doc) < startIndex) {
                 presTargetDoc.opacity = 0;
             }
-            if (doc.presFadeButton && this.childDocs.indexOf(doc) < startIndex) {
-                presTargetDoc.opacity = 0.5;
-            }
         });
     }
 
     updateMinimize = () => {
         const srcContext = Cast(this.rootDoc.presCollection, Doc, null);
+        this.turnOffEdit();
         if (srcContext) {
             if (srcContext.miniPres) {
                 document.removeEventListener("keydown", this.keyEvents, false);
@@ -461,7 +512,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
     }
     childLayoutTemplate = () => this.rootDoc._viewType !== CollectionViewType.Stacking ? undefined : this.presElement;
     removeDocument = (doc: Doc) => Doc.RemoveDocFromList(this.dataDoc, this.fieldKey, doc);
-    getTransform = () => this.props.ScreenToLocalTransform();// listBox padding-left and pres-box-cont minHeight - .translate(-5, -65)
+    getTransform = () => this.props.ScreenToLocalTransform().translate(-5, -65);// listBox padding-left and pres-box-cont minHeight
     panelHeight = () => this.props.PanelHeight() - 40;
     active = (outsideReaction?: boolean) => ((Doc.GetSelectedTool() === InkTool.None && !this.layoutDoc.isBackground) &&
         (this.layoutDoc.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false)
@@ -498,10 +549,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
     //Regular click
     @action
     selectElement = (doc: Doc) => {
-        // this._selectedArray = [];
         this.gotoDocument(this.childDocs.indexOf(doc), NumCast(this.itemIndex));
-        // this._selectedArray.push(this.childDocs[this.childDocs.indexOf(doc)]);
-        // console.log(this._selectedArray);
     }
 
     //Command click
@@ -526,8 +574,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         }
     }
 
-
-
     //Esc click
     @action
     keyEvents = (e: KeyboardEvent) => {
@@ -566,69 +612,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
     @observable private pathBoolean: boolean = false;
     @observable private expandBoolean: boolean = false;
 
-    // For toggling transition toolbar
-    @action toggleTransitionTools = () => {
-        this.transitionTools = !this.transitionTools;
-        this.newDocumentTools = false;
-        this.progressivizeTools = false;
-        this.moreInfoTools = false;
-        this.playTools = false;
-    }
-    // For toggling the add new document dropdown
-    @action toggleNewDocument = () => {
-        this.newDocumentTools = !this.newDocumentTools;
-        this.transitionTools = false;
-        this.progressivizeTools = false;
-        this.moreInfoTools = false;
-        this.playTools = false;
-    }
-    // For toggling the tools for progressivize
-    @action toggleProgressivize = () => {
-        this.progressivizeTools = !this.progressivizeTools;
-        const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
-        const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
-        targetDoc.editZoomProgressivize = false;
-        targetDoc.editProgressivize = false;
-        this.transitionTools = false;
-        this.newDocumentTools = false;
-        this.moreInfoTools = false;
-        this.playTools = false;
-    }
-    // For toggling the tools for more info
-    @action toggleMoreInfo = () => {
-        this.moreInfoTools = !this.moreInfoTools;
-        this.transitionTools = false;
-        this.newDocumentTools = false;
-        this.progressivizeTools = false;
-        this.playTools = false;
-    }
-    // For toggling the options when the user wants to select play
-    @action togglePlay = () => {
-        this.playTools = !this.playTools;
-        this.transitionTools = false;
-        this.newDocumentTools = false;
-        this.progressivizeTools = false;
-        this.moreInfoTools = false;
-    }
-
-    // For toggling the options when the user wants to select play
-    @action togglePresent = () => {
-        this.presentTools = !this.presentTools;
-        this.playTools = false;
-        this.transitionTools = false;
-        this.newDocumentTools = false;
-        this.progressivizeTools = false;
-        this.moreInfoTools = false;
-    }
-
-    @action toggleAllDropdowns() {
-        this.transitionTools = false;
-        this.newDocumentTools = false;
-        this.progressivizeTools = false;
-        this.moreInfoTools = false;
-        this.playTools = false;
-    }
-
     @undoBatch
     @action
     viewPaths = async () => {
@@ -831,20 +814,19 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                                 <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={() => targetDoc.presEffect = 'Roll'}>Roll</div>
                             </div>
                         </div>
-                        <div className="presBox-subheading" style={{ display: effect === 'None' ? "none" : "block" }}>Effect direction</div>
-                        <div className="presBox-reactiveGrid" style={{ display: effect === 'None' ? "none" : "grid" }}>
-                            <div className="effectDirection" style={{ display: "grid", width: 40 }}>
-                                <Tooltip title={<><div className="dash-tooltip">{"Enter from left"}</div></>}><div style={{ gridColumn: 1, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === "left" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'left'}><FontAwesomeIcon icon={"angle-right"} /></div></Tooltip>
-                                <Tooltip title={<><div className="dash-tooltip">{"Enter from right"}</div></>}><div style={{ gridColumn: 3, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === "right" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'right'}><FontAwesomeIcon icon={"angle-left"} /></div></Tooltip>
-                                <Tooltip title={<><div className="dash-tooltip">{"Enter from top"}</div></>}><div style={{ gridColumn: 2, gridRow: 1, justifySelf: 'center', color: targetDoc.presEffectDirection === "top" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'top'}><FontAwesomeIcon icon={"angle-down"} /></div></Tooltip>
-                                <Tooltip title={<><div className="dash-tooltip">{"Enter from bottom"}</div></>}><div style={{ gridColumn: 2, gridRow: 3, justifySelf: 'center', color: targetDoc.presEffectDirection === "bottom" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'bottom'}><FontAwesomeIcon icon={"angle-up"} /></div></Tooltip>
-                                <Tooltip title={<><div className="dash-tooltip">{"Enter from center"}</div></>}><div style={{ gridColumn: 2, gridRow: 2, width: 10, height: 10, alignSelf: 'center', justifySelf: 'center', border: targetDoc.presEffectDirection ? "solid 2px black" : "solid 2px #5a9edd", borderRadius: "100%" }} onClick={() => targetDoc.presEffectDirection = false}></div></Tooltip>
-                            </div>
+                        <div className="ribbon-doubleButton" style={{ display: effect === 'None' ? "none" : "inline-flex" }}>
+                            <div className="presBox-subheading" >Effect direction</div>
                             <div className="ribbon-property">
                                 {this.effectDirection}
                             </div>
                         </div>
-
+                        <div className="effectDirection" style={{ display: effect === 'None' ? "none" : "grid", width: 40 }}>
+                            <Tooltip title={<><div className="dash-tooltip">{"Enter from left"}</div></>}><div style={{ gridColumn: 1, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === "left" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'left'}><FontAwesomeIcon icon={"angle-right"} /></div></Tooltip>
+                            <Tooltip title={<><div className="dash-tooltip">{"Enter from right"}</div></>}><div style={{ gridColumn: 3, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === "right" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'right'}><FontAwesomeIcon icon={"angle-left"} /></div></Tooltip>
+                            <Tooltip title={<><div className="dash-tooltip">{"Enter from top"}</div></>}><div style={{ gridColumn: 2, gridRow: 1, justifySelf: 'center', color: targetDoc.presEffectDirection === "top" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'top'}><FontAwesomeIcon icon={"angle-down"} /></div></Tooltip>
+                            <Tooltip title={<><div className="dash-tooltip">{"Enter from bottom"}</div></>}><div style={{ gridColumn: 2, gridRow: 3, justifySelf: 'center', color: targetDoc.presEffectDirection === "bottom" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'bottom'}><FontAwesomeIcon icon={"angle-up"} /></div></Tooltip>
+                            <Tooltip title={<><div className="dash-tooltip">{"Enter from center"}</div></>}><div style={{ gridColumn: 2, gridRow: 2, width: 10, height: 10, alignSelf: 'center', justifySelf: 'center', border: targetDoc.presEffectDirection ? "solid 2px black" : "solid 2px #5a9edd", borderRadius: "100%" }} onClick={() => targetDoc.presEffectDirection = false}></div></Tooltip>
+                        </div>
                     </div>
                     <div className="ribbon-final-box">
                         <div className={this._selectedArray.length === 0 ? "ribbon-final-button" : "ribbon-final-button-hidden"} onClick={() => this.applyTo(this._selectedArray)}>
@@ -887,9 +869,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         });
     }
 
-    public inputRef = React.createRef<HTMLInputElement>();
-
-
+    private inputRef = React.createRef<HTMLInputElement>();
 
     @computed get optionsDropdown() {
         const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
@@ -899,14 +879,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                 <div>
                     <div className={'presBox-ribbon'} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
                         <div className="ribbon-box">
-                            {this.stringType} options
                             <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.VID || targetDoc.type === DocumentType.AUDIO ? "inline-flex" : "none" }}>
                                 <div className="ribbon-button" style={{ backgroundColor: activeItem.presProgressivize ? "#aedef8" : "" }} onClick={this.progressivizeChild}>Start automatically</div>
                                 <div className="ribbon-button" style={{ display: "flex", backgroundColor: targetDoc.editProgressivize ? "#aedef8" : "" }} onClick={this.editProgressivize}>Start manually</div>
                             </div>
                             <div className="ribbon-doubleButton" style={{ display: "flex" }}>
-                                <div className="ribbon-button" style={{ backgroundColor: activeItem.zoomProgressivize ? "#aedef8" : "" }} onClick={this.progressivizeZoom}>Open document</div>
-                                <div className="ribbon-button" style={{ display: "flex", backgroundColor: targetDoc.editZoomProgressivize ? "#aedef8" : "" }} onClick={this.editZoomProgressivize}>Open parent collection</div>
+                                <div className="ribbon-button" style={{ backgroundColor: activeItem.openDocument ? "#aedef8" : "" }} onClick={() => { activeItem.openDocument = !activeItem.openDocument }}>Open document</div>
                             </div>
                             <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.WEB ? "inline-flex" : "none" }}>
                                 <div className="ribbon-button" onClick={this.progressivizeText}>Store original website</div>
@@ -935,11 +913,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                             <div className="title" style={{ alignSelf: 'center' }}>Title</div>
                             <div className="content">Text goes here</div>
                         </div>
-                        <div className="layout" style={{ border: this.layout === 'twoColumns' ? 'solid 2px #5b9ddd' : '' }} onClick={() => runInAction(() => { this.layout = 'twoColumns'; this.createNewSlide(this.layout); })}>
+                        {/* <div className="layout" style={{ border: this.layout === 'twoColumns' ? 'solid 2px #5b9ddd' : '' }} onClick={() => runInAction(() => { this.layout = 'twoColumns'; this.createNewSlide(this.layout); })}>
                             <div className="title" style={{ alignSelf: 'center', gridColumn: '1/3' }}>Title</div>
                             <div className="content" style={{ gridColumn: 1, gridRow: 2 }}>Column one text</div>
                             <div className="content" style={{ gridColumn: 2, gridRow: 2 }}>Column two text</div>
-                        </div>
+                        </div> */}
                     </div>
                 </div>
             </div >
@@ -1009,17 +987,16 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
     createNewSlide = (layout?: string, title?: string, freeform?: boolean) => {
         console.log("whats going on?");
         let doc = undefined;
+        if (layout) doc = this.createTemplate(layout);
         if (freeform && layout) doc = this.createTemplate(layout, title);
-        if (!freeform) doc = Docs.Create.TextDocument("", { _nativeWidth: 400, _width: 225, title: title });
+        if (!freeform && !layout) doc = Docs.Create.TextDocument("", { _nativeWidth: 400, _width: 225, title: title });
         const presCollection = Cast(this.layoutDoc.presCollection, Doc, null);
         const data = Cast(presCollection.data, listSpec(Doc));
         const presData = Cast(this.rootDoc.data, listSpec(Doc));
-        console.log(data);
-        console.log(doc);
         if (data && doc && presData) {
-            console.log("data and doc");
             data.push(doc);
             DockedFrameRenderer.PinDoc(doc, false);
+            this.gotoDocument(this.childDocs.length, this.itemIndex);
         }
     }
 
@@ -1029,56 +1006,32 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         let x = 0;
         let y = 0;
         if (activeItem && targetDoc) {
-            x = NumCast(targetDoc._x);
-            y = NumCast(targetDoc._y) + NumCast(targetDoc._height) + 20;
+            x = NumCast(targetDoc.x);
+            y = NumCast(targetDoc.y) + NumCast(targetDoc._height) + 20;
         }
         let doc = undefined;
-        const title = Docs.Create.TextDocument("Click to change title", {
-            title: "Slide title", _width: 380, _height: 60, x: 10, y: 58, _fontSize: "24pt",
-        });
-        const subtitle = Docs.Create.TextDocument("Click to change subtitle", {
-            title: "Slide subtitle", _width: 380, _height: 50, x: 10, y: 118, _fontSize: "16pt"
-        });
-        const header = Docs.Create.TextDocument("Click to change header", {
-            title: "Slide header", _width: 380, _height: 65, x: 10, y: 80, _fontSize: "20pt"
-        });
-        const contentTitle = Docs.Create.TextDocument("Click to change title", {
-            title: "Slide title", _width: 380, _height: 60, x: 10, y: 10, _fontSize: "24pt"
-        });
-        const content = Docs.Create.TextDocument("Click to change texte", {
-            title: "Slide text", _width: 380, _height: 145, x: 10, y: 70, _fontSize: "14pt"
-        });
-        const content1 = Docs.Create.TextDocument("Click to change text", {
-            title: "Column 1", _width: 185, _height: 140, x: 10, y: 80, _fontSize: "14pt"
-        });
-        const content2 = Docs.Create.TextDocument("Click to change text", {
-            title: "Column 2", _width: 185, _height: 140, x: 205, y: 80, _fontSize: "14pt"
-        });
+        const title = Docs.Create.TextDocument("Click to change title", { title: "Slide title", _width: 380, _height: 60, x: 10, y: 58, _fontSize: "24pt", });
+        const subtitle = Docs.Create.TextDocument("Click to change subtitle", { title: "Slide subtitle", _width: 380, _height: 50, x: 10, y: 118, _fontSize: "16pt" });
+        const header = Docs.Create.TextDocument("Click to change header", { title: "Slide header", _width: 380, _height: 65, x: 10, y: 80, _fontSize: "20pt" });
+        const contentTitle = Docs.Create.TextDocument("Click to change title", { title: "Slide title", _width: 380, _height: 60, x: 10, y: 10, _fontSize: "24pt" });
+        const content = Docs.Create.TextDocument("Click to change texte", { title: "Slide text", _width: 380, _height: 145, x: 10, y: 70, _fontSize: "14pt" });
+        const content1 = Docs.Create.TextDocument("Click to change text", { title: "Column 1", _width: 185, _height: 140, x: 10, y: 80, _fontSize: "14pt" });
+        const content2 = Docs.Create.TextDocument("Click to change text", { title: "Column 2", _width: 185, _height: 140, x: 205, y: 80, _fontSize: "14pt" });
         switch (layout) {
             case 'blank':
-                doc = Docs.Create.FreeformDocument([], {
-                    title: input ? input : "Blank slide", _width: 400, _height: 225, _fitToBox: true, x: x, y: y
-                });
+                doc = Docs.Create.FreeformDocument([], { title: input ? input : "Blank slide", _width: 400, _height: 225, _fitToBox: true, x: x, y: y });
                 break;
             case 'title':
-                doc = Docs.Create.FreeformDocument([title, subtitle], {
-                    title: input ? input : "Title slide", _width: 400, _height: 225, _fitToBox: true, x: x, y: y
-                });
+                doc = Docs.Create.FreeformDocument([title, subtitle], { title: input ? input : "Title slide", _width: 400, _height: 225, _fitToBox: true, x: x, y: y });
                 break;
             case 'header':
-                doc = Docs.Create.FreeformDocument([header], {
-                    title: input ? input : "Section header", _width: 400, _height: 225, _fitToBox: true, x: x, y: y
-                });
+                doc = Docs.Create.FreeformDocument([header], { title: input ? input : "Section header", _width: 400, _height: 225, _fitToBox: true, x: x, y: y });
                 break;
             case 'content':
-                doc = Docs.Create.FreeformDocument([contentTitle, content], {
-                    title: input ? input : "Title and content", _width: 400, _height: 225, _fitToBox: true, x: x, y: y
-                });
+                doc = Docs.Create.FreeformDocument([contentTitle, content], { title: input ? input : "Title and content", _width: 400, _height: 225, _fitToBox: true, x: x, y: y });
                 break;
             case 'twoColumns':
-                doc = Docs.Create.FreeformDocument([contentTitle, content1, content2], {
-                    title: input ? input : "Title and two columns", _width: 400, _height: 225, _fitToBox: true, x: x, y: y
-                });
+                doc = Docs.Create.FreeformDocument([contentTitle, content1, content2], { title: input ? input : "Title and two columns", _width: 400, _height: 225, _fitToBox: true, x: x, y: y });
                 break;
             default:
                 break;
@@ -1086,6 +1039,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         return doc;
     }
 
+    // Dropdown that appears for autoplay
     @computed get playDropdown() {
         return (
             <div className={`dropdown-play ${this.playTools ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
@@ -1099,30 +1053,27 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         );
     }
 
+    // Dropdown that appears when the user wants to begin presenting (either minimize or sidebar view)
     @computed get presentDropdown() {
         return (
             <div className={`dropdown-play ${this.presentTools ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
                 <div className="dropdown-play-button" onClick={this.updateMinimize}>
                     Minimize
                 </div>
-                <div className="dropdown-play-button" onClick={() => this.startOrResetPres(0)}>
+                <div className="dropdown-play-button" onClick={() => { this.startOrResetPres(0); this.turnOffEdit(); }}>
                     Sidebar view
                 </div>
             </div>
         );
     }
 
-    // progressivizeOptions = (viewType: string) => {
-    //     const buttons = [];
-    //     buttons.push(<div className="ribbon-button" onClick={this.progressivize}>Child documents</div>);
-    //     buttons.push(<div className="ribbon-button" onClick={() => console.log("hide after")}>Internal zoom</div>);
-    //     buttons.push(<div className="ribbon-button" onClick={() => console.log("hide after")}>Bullet points</div>);
-    //     if (viewType === "rtf") {
-    //         buttons.push(<div className="ribbon-button" title="Progressivize bullet points" onClick={() => console.log("hide after")}>Bullet points</div>);
-    //     }
-    //     return buttons;
-    // }
+    // For toggling the options when the user wants to select play
+    @action togglePlay = () => { this.playTools = !this.playTools; }
 
+    // For toggling the options when the user wants to select play
+    @action togglePresent = () => { this.presentTools = !this.presentTools; }
+
+    // Case in which the document has keyframes to navigate to next key frame
     @undoBatch
     @action
     nextKeyframe = (tagDoc: Doc): void => {
@@ -1178,13 +1129,16 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
         const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null);
         let type: string = '';
-        switch (targetDoc.type) {
-            case DocumentType.PDF: type = "PDF"; break;
-            case DocumentType.RTF: type = "Text node"; break;
-            case DocumentType.COL: type = "Collection"; break;
-            case DocumentType.AUDIO: type = "Audio"; break;
-            case DocumentType.VID: type = "Video"; break;
-            default: type = "Other node"; break;
+        if (activeItem) {
+            switch (targetDoc.type) {
+                case DocumentType.PDF: type = "PDF"; break;
+                case DocumentType.RTF: type = "Text node"; break;
+                case DocumentType.COL: type = "Collection"; break;
+                case DocumentType.AUDIO: type = "Audio"; break;
+                case DocumentType.VID: type = "Video"; break;
+                case DocumentType.IMG: type = "Image"; break;
+                default: type = "Other node"; break;
+            }
         }
         return type;
     }
@@ -1206,7 +1160,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                             <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.COL || targetDoc.type === DocumentType.IMG ? "inline-flex" : "none" }}>
                                 <div className="ribbon-button" style={{ backgroundColor: activeItem.zoomProgressivize ? "#aedef8" : "" }} onClick={this.progressivizeZoom}>Internal zoom</div>
                                 <div className="ribbon-button" style={{ display: activeItem.zoomProgressivize ? "flex" : "none", backgroundColor: targetDoc.editZoomProgressivize ? "#aedef8" : "" }} onClick={this.editZoomProgressivize}>Viewfinder</div>
-                                <div className="ribbon-button" style={{ display: activeItem.zoomProgressivize ? "flex" : "none", backgroundColor: targetDoc.editSnapZoomProgressivize ? "#aedef8" : "" }} onClick={this.editSnapZoomProgressivize}>Snapshot</div>
+                                {/* <div className="ribbon-button" style={{ display: activeItem.zoomProgressivize ? "flex" : "none", backgroundColor: targetDoc.editSnapZoomProgressivize ? "#aedef8" : "" }} onClick={this.editSnapZoomProgressivize}>Snapshot</div> */}
                             </div>
                             <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.RTF ? "inline-flex" : "none" }}>
                                 <div className="ribbon-button" onClick={this.progressivizeText}>Text progressivize</div>
@@ -1242,6 +1196,18 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         }
     }
 
+    turnOffEdit = () => {
+        this.childDocs.forEach((doc, index) => {
+            const targetDoc = Cast(doc.presentationTargetDoc, Doc, null);
+            targetDoc.editSnapZoomProgressivize = false;
+            targetDoc.editZoomProgressivize = false;
+            targetDoc.editScrollProgressivize = false;
+            if (doc.type === DocumentType.WEB) {
+                doc.presWebsite = doc.data;
+            }
+        });
+    }
+
     //Toggle whether the user edits or not
     @action
     editSnapZoomProgressivize = (e: React.MouseEvent) => {
@@ -1703,13 +1669,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         return width;
     }
 
-
     @computed get toolbar() {
         const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
         if (activeItem) {
             return (
                 <>
-                    <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={this.toggleNewDocument}><FontAwesomeIcon icon={"plus"} />
+                    <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={() => runInAction(() => { this.newDocumentTools = !this.newDocumentTools; })}><FontAwesomeIcon icon={"plus"} />
                         <FontAwesomeIcon className={`dropdown ${this.newDocumentTools ? "active" : ""}`} icon={"angle-down"} />
                     </div></Tooltip>
                     <div className="toolbar-divider" />
@@ -1735,7 +1700,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                         <FontAwesomeIcon className={`dropdown ${this.progressivizeTools ? "active" : ""}`} icon={"angle-down"} />
                     </div></Tooltip>
                     <div className="toolbar-divider" /> */}
-                    <div className="toolbar-button" style={{ position: 'absolute', right: 23, transform: 'rotate(45deg)', fontSize: 16 }}>
+                    {/* <div className="toolbar-button" style={{ position: 'absolute', right: 23, transform: 'rotate(45deg)', fontSize: 16 }}>
                         <FontAwesomeIcon className={"toolbar-thumbtack"} icon={"thumbtack"} />
                     </div>
                     <div className={`toolbar-button ${this.moreInfoTools ? "active" : ""}`} onClick={this.toggleMoreInfo}>
@@ -1744,16 +1709,17 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                             <div className="toolbar-moreInfoBall" />
                             <div className="toolbar-moreInfoBall" />
                         </div>
-                    </div>
+                    </div> */}
                 </>
             );
         } else {
             return (
                 <>
-                    <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={this.toggleNewDocument}><FontAwesomeIcon icon={"plus"} />
+                    <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={() => runInAction(() => { this.newDocumentTools = !this.newDocumentTools; })}>
+                        <FontAwesomeIcon icon={"plus"} />
                         <FontAwesomeIcon className={`dropdown ${this.newDocumentTools ? "active" : ""}`} icon={"angle-down"} />
                     </div></Tooltip>
-                    <div className="toolbar-button" style={{ position: 'absolute', right: 23, transform: 'rotate(45deg)', fontSize: 16 }}>
+                    {/* <div className="toolbar-button" style={{ position: 'absolute', right: 23, transform: 'rotate(45deg)', fontSize: 16 }}>
                         <FontAwesomeIcon className={"toolbar-thumbtack"} icon={"thumbtack"} />
                     </div>
                     <div className={`toolbar-button ${this.moreInfoTools ? "active" : ""}`} onClick={this.toggleMoreInfo}>
@@ -1762,68 +1728,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                             <div className="toolbar-moreInfoBall" />
                             <div className="toolbar-moreInfoBall" />
                         </div>
-                    </div>
+                    </div> */}
                 </>
             );
         }
     }
 
-    private _itemRef: React.RefObject<HTMLDivElement> = React.createRef();
-
-
-    // protected createPresDropTarget = (ele: HTMLDivElement) => {
-    //     console.log("created?");
-    //     this.treedropDisposer?.();
-    //     ele && (this.treedropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc, this.onInternalPreDrop.bind(this)));
-    //     if (ele) {
-    //         console.log("ele: " + ele.className)
-    //     }
-    // }
-
-    // protected onInternalPreDrop(e: Event, de: DragManager.DropEvent, targetAction: dropActionType) {
-    //     console.log("preDrop?")
-    //     if (de.complete.docDragData) {
-    //         // if targetDropAction is, say 'alias', but we're just dragging within a collection, we want to ignore the targetAction.
-    //         // otherwise, the targetAction should become the actual action (which can still be overridden by the userDropAction -eg, shift/ctrl keys)
-    //         if (targetAction && !de.complete.docDragData.draggedDocuments.some(d => d.context === this.props.Document && this.childDocs.includes(d))) {
-    //             de.complete.docDragData.dropAction = targetAction;
-    //         }
-    //         e.stopPropagation();
-    //     }
-    // }
-
-    // @action
-    // protected onInternalDrop(e: Event, de: DragManager.DropEvent): boolean {
-    //     console.log("drop in pres")
-    //     const docDragData = de.complete.docDragData;
-    //     ScriptCast(this.props.Document.dropConverter)?.script.run({ dragData: docDragData });
-    //     if (docDragData && this.props.addDocument) {
-    //         console.log("docDragData && this.props.addDocument");
-    //         let added = false;
-    //         const dropaction = docDragData.dropAction || docDragData.userDropAction;
-    //         if (dropaction && dropaction !== "move") {
-    //             console.log("dropaction && dropaction !== move");
-    //             added = this.props.addDocument(docDragData.droppedDocuments);
-    //         } else if (docDragData.moveDocument) {
-    //             console.log("docDragData.moveDocument");
-    //             const movedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] === d);
-    //             const addedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] !== d);
-    //             const res = addedDocs.length ? this.props.addDocument(addedDocs) : true;
-    //             if (movedDocs.length) {
-    //                 const canAdd = this.props.Document._viewType === CollectionViewType.Pile || de.embedKey ||
-    //                     Doc.AreProtosEqual(Cast(movedDocs[0].annotationOn, Doc, null), this.props.Document);
-    //                 added = docDragData.moveDocument(movedDocs, this.props.Document, canAdd ? this.props.addDocument : returnFalse);
-    //             } else added = res;
-    //         } else {
-    //             console.log("else");
-    //             added = this.props.addDocument(docDragData.droppedDocuments);
-    //         }
-    //         added && e.stopPropagation();
-    //         return added;
-    //     }
-    //     return false;
-    // }
-
     render() {
         this.childDocs.slice(); // needed to insure that the childDocs are loaded for looking up fields
         const mode = StrCast(this.rootDoc._viewType) as CollectionViewType;
@@ -1872,12 +1782,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
             </div>
             <div id="toolbarContainer" className={`presBox-toolbar ${this.layoutDoc.presStatus === "edit" ? "active" : ""}`}> {this.toolbar} </div>
             {this.newDocumentToolbarDropdown}
-            {/* {this.newDocumentDropdown}
-            {this.moreInfoDropdown}
-            {this.transitionDropdown}
-            {this.progressivizeDropdown} */}
             <div className="presBox-listCont">
-                {/* ref={this.createPresDropTarget}> */}
                 {mode !== CollectionViewType.Invalid ?
                     <CollectionView {...this.props}
                         ContainingCollectionDoc={this.props.Document}
@@ -1890,8 +1795,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                         removeDocument={returnFalse}
                         dontRegisterView={true}
                         focus={this.selectElement}
-                        // presMultiSelect={this.multiSelect}
-                        // ScreenToLocalTransform={Transform.Identity} />
                         ScreenToLocalTransform={this.getTransform} />
                     : (null)
                 }
diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx
index 90eb8580e..b3d8cca98 100644
--- a/src/client/views/presentationview/PresElementBox.tsx
+++ b/src/client/views/presentationview/PresElementBox.tsx
@@ -251,10 +251,6 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
         const dragData = new DragManager.DocumentDragData(PresBox.Instance.sortArray().map(doc => doc));
         // let value = this.getValue(this._heading);
         // value = typeof value === "string" ? `"${value}"` : value;
-        PresBox.Instance._dragArray.map(ele => {
-            ele.style.backgroundColor = "#d5dce2";
-            ele.style.borderRadius = '5px';
-        });
         if (activeItem) {
             DragManager.StartDocumentDrag(PresBox.Instance._dragArray.map(ele => ele), dragData, e.clientX, e.clientY);
             activeItem.dragging = true;
@@ -276,26 +272,21 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
                 onClick={e => {
                     e.stopPropagation();
                     e.preventDefault();
+                    // Command/ control click
                     if (e.ctrlKey || e.metaKey) {
                         PresBox.Instance.multiSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!);
-                        console.log("cmmd click");
+                        // Shift click
                     } else if (e.shiftKey) {
                         PresBox.Instance.shiftSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!);
+                        // Regular click
                     } else {
-                        PresBox.Instance.selectElement(this.rootDoc);
+                        this.props.focus(this.rootDoc);
                         PresBox.Instance._eleArray = [];
                         PresBox.Instance._eleArray.push(this._itemRef.current!);
                         PresBox.Instance._dragArray = [];
                         PresBox.Instance._dragArray.push(this._dragRef.current!);
-                        console.log("normal click");
                     }
                 }}
-                // onClick={e => {
-                //     if (this.props.active(true)) {
-                //         e.stopPropagation();
-                //         e.preventDefault();
-                //     }
-                // }}
                 onPointerDown={this.headerDown}
             >
                 <>
-- 
cgit v1.2.3-70-g09d2


From 4051758f3cef5e353cb24c699f4594fa4be81758 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Tue, 4 Aug 2020 13:10:13 -0500
Subject: several UI changes and consistency updates around the system

---
 src/client/views/ContextMenu.scss                      |  5 ++++-
 src/client/views/DocumentButtonBar.scss                |  8 ++++++--
 src/client/views/DocumentButtonBar.tsx                 |  2 +-
 src/client/views/MainView.tsx                          |  4 ++--
 src/client/views/PropertiesButtons.tsx                 |  2 +-
 src/client/views/collections/CollectionLinearView.scss |  2 +-
 src/client/views/collections/CollectionMenu.tsx        |  2 +-
 src/client/views/collections/CollectionTreeView.scss   | 15 +++++++++++----
 .../collections/collectionFreeForm/PropertiesView.scss | 11 +++++++++++
 .../collections/collectionFreeForm/PropertiesView.tsx  |  4 ++--
 src/client/views/linking/LinkEditor.scss               |  3 ++-
 src/client/views/linking/LinkEditor.tsx                |  6 +++---
 src/client/views/nodes/DocumentLinksButton.scss        |  8 +++++++-
 src/client/views/nodes/DocumentLinksButton.tsx         |  8 ++++----
 src/client/views/nodes/FontIconBox.scss                |  5 +++++
 src/client/views/nodes/FontIconBox.tsx                 | 18 ++++++++----------
 16 files changed, 69 insertions(+), 34 deletions(-)

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

diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss
index 86e0a568a..7467bc043 100644
--- a/src/client/views/ContextMenu.scss
+++ b/src/client/views/ContextMenu.scss
@@ -7,7 +7,7 @@
     box-shadow: $intermediate-color 0.2vw 0.2vw 0.4vw;
     flex-direction: column;
     background: whitesmoke;
-    padding-top: 10px; 
+    padding-top: 10px;
     padding-bottom: 10px;
     border-radius: 15px;
     border: solid #BBBBBBBB 1px;
@@ -72,6 +72,7 @@
         margin-left: 5px;
     }
 }
+
 .contextMenu-description {
     // width: 11vw; //10vw
     background: whitesmoke;
@@ -100,6 +101,8 @@
     border-color: $intermediate-color; //  rgb(187, 186, 186);
     border-bottom-style: solid;
     border-top-style: solid;
+
+    cursor: pointer;
 }
 
 .contextMenu-itemSelected {
diff --git a/src/client/views/DocumentButtonBar.scss b/src/client/views/DocumentButtonBar.scss
index c2ca93900..09ae14016 100644
--- a/src/client/views/DocumentButtonBar.scss
+++ b/src/client/views/DocumentButtonBar.scss
@@ -64,9 +64,13 @@ $linkGap : 3px;
     text-align: center;
     border-radius: 50%;
     pointer-events: auto;
-    color: $dark-color;
-    border: $dark-color 1px solid;
+    background-color: $dark-color;
+    border: none;
     transition: 0.2s ease all;
+
+    &:hover {
+        background-color: $main-accent;
+    }
 }
 
 .documentButtonBar-linker:hover {
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index d45531b76..8748b1880 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -198,7 +198,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
         const isPinned = targetDoc && Doc.isDocPinned(targetDoc);
         return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}</div></>}>
             <div className="documentButtonBar-linker"
-                style={{ backgroundColor: isPinned ? "black" : "white", color: isPinned ? "white" : "black" }}
+                style={{ backgroundColor: isPinned ? "white" : "", color: isPinned ? "black" : "white", border: isPinned ? "black 1px solid " : "" }}
                 onClick={e => DockedFrameRenderer.PinDoc(targetDoc, isPinned)}>
                 <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin"
                 />
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index a544c52d2..e9b9be49d 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -553,7 +553,7 @@ export class MainView extends React.Component {
                 <div className="mainView-flyoutContainer" style={{ width: this.flyoutWidth }}>
                     {this.flyoutWidth !== 0 ? <div className="mainView-libraryHandle"
                         onPointerDown={this.onFlyoutPointerDown}
-                        style={{ backgroundColor: 'lightgrey' }}>
+                        style={{ backgroundColor: '#8c8b8b' }}>
                         <span title="library View Dragger" style={{
                             width: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "100%" : "3vw",
                             //height: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "100%" : "100vh",
@@ -561,7 +561,7 @@ export class MainView extends React.Component {
                             top: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "" : "0"
                         }} />
                         <div className="mainview-libraryHandle-icon">
-                            <FontAwesomeIcon icon="chevron-left" color="black" size="sm" />
+                            <FontAwesomeIcon icon="chevron-left" color="white" size="sm" />
                         </div>
                     </div> : null}
                     <div className="mainView-libraryFlyout" style={{
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index 37ee3d9e0..c25d58c60 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -563,7 +563,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
             title={<><div className="dash-tooltip">{this.selectedDoc?._fitToBox ? "Stop Fitting Content" : "Fit Content"}</div></>} placement="top">
             <div>
                 <div className={"propertiesButtons-linkButton-empty"}
-                    style={{ backgroundColor: this.selectedDoc?._fitToBox ? "#a0a0a0" : "" }}
+                    style={{ backgroundColor: this.selectedDoc?._fitToBox ? "white" : "" }}
                     onPointerDown={this.changeFitToBox}>
                     {<FontAwesomeIcon className="documentdecorations-icon"
                         color={this.selectedDoc?._fitToBox ? "black" : "white"}
diff --git a/src/client/views/collections/CollectionLinearView.scss b/src/client/views/collections/CollectionLinearView.scss
index b8b72e756..f5c4299a9 100644
--- a/src/client/views/collections/CollectionLinearView.scss
+++ b/src/client/views/collections/CollectionLinearView.scss
@@ -2,7 +2,7 @@
 @import "../_nodeModuleOverrides";
 
 .collectionLinearView-outer {
-    overflow: hidden;
+    overflow: visible;
     height: 100%;
 
     .collectionLinearView {
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 20df22846..53c2495d0 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -185,7 +185,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
         initialize: (button: Doc) => { button['target-docFilters'] = this.target._docFilters instanceof ObjectField ? ObjectField.MakeCopy(this.target._docFilters as any as ObjectField) : ""; },
     };
 
-    @computed get _freeform_commands() { return Doc.UserDoc().noviceMode ? [this._viewCommand, this._saveFilterCommand] : [this._viewCommand, this._saveFilterCommand, this._contentCommand, this._templateCommand, this._narrativeCommand]; }
+    @computed get _freeform_commands() { return Doc.UserDoc().noviceMode ? [this._viewCommand] : [this._viewCommand, this._saveFilterCommand, this._contentCommand, this._templateCommand, this._narrativeCommand]; }
     @computed get _stacking_commands() { return Doc.UserDoc().noviceMode ? undefined : [this._contentCommand, this._templateCommand]; }
     @computed get _masonry_commands() { return Doc.UserDoc().noviceMode ? undefined : [this._contentCommand, this._templateCommand]; }
     @computed get _schema_commands() { return Doc.UserDoc().noviceMode ? undefined : [this._templateCommand, this._narrativeCommand]; }
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index 50f0534bd..c9bf82406 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -22,7 +22,7 @@
     ul {
         list-style: none;
         padding-left: 20px;
-        margin-bottom: 1px;// otherwise vertical scrollbars may pop up for no apparent reason....
+        margin-bottom: 1px; // otherwise vertical scrollbars may pop up for no apparent reason....
     }
 
 
@@ -35,7 +35,7 @@
         width: 15px;
         color: $intermediate-color;
         margin-top: 3px;
-        transform: scale(1.3, 1.3); 
+        transform: scale(1.3, 1.3);
         border: #80808030 1px solid;
         border-radius: 4px;
     }
@@ -67,8 +67,10 @@
     margin-left: 3px;
     display: none;
 }
+
 .collectionTreeView-keyHeader:hover {
     background: #797777;
+    cursor: pointer;
 }
 
 .collectionTreeView-subtitle {
@@ -89,8 +91,10 @@
     height: 17px;
     width: 15px;
 }
+
 .treeViewItem-openRight:hover {
     background: #797777;
+    cursor: pointer;
 }
 
 .treeViewItem-border {
@@ -106,10 +110,12 @@
     .editableView-container-editing-oneLine {
         min-width: 15px;
     }
+
     .documentView-node-topmost {
         width: unset;
     }
-    > svg {
+
+    >svg {
         display: none;
     }
 
@@ -119,7 +125,8 @@
     .collectionTreeView-keyHeader {
         display: inherit;
     }
-    > svg {
+
+    >svg {
         display: inherit;
     }
 
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index aede3842e..9560de2f5 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -641,4 +641,15 @@
             margin-top: 2px;
         }
     }
+}
+
+.editable-title {
+    border: none;
+    padding: 6px;
+    padding-bottom: 2px;
+
+
+    &:hover {
+        border: 0.75px solid rgb(122, 28, 28);
+    }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index f04c5159c..e2e026ca2 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -358,13 +358,13 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
     @computed get editableTitle() {
-        return <EditableView
+        return <div className="editable-title"><EditableView
             key="editableView"
             contents={StrCast(this.selectedDoc?.title)}
             height={25}
             fontSize={14}
             GetValue={() => StrCast(this.selectedDoc?.title)}
-            SetValue={this.setTitle} />;
+            SetValue={this.setTitle} /> </div>;
     }
 
     @undoBatch
diff --git a/src/client/views/linking/LinkEditor.scss b/src/client/views/linking/LinkEditor.scss
index d26b7920a..7e6999cdc 100644
--- a/src/client/views/linking/LinkEditor.scss
+++ b/src/client/views/linking/LinkEditor.scss
@@ -89,7 +89,7 @@
             /* float: right; */
             border-radius: 7px;
             font-size: 9px;
-            background-color: black;
+            background: black;
             /* padding: 3px; */
             padding-top: 4px;
             padding-left: 7px;
@@ -100,6 +100,7 @@
 
             &:hover {
                 cursor: pointer;
+                background: grey;
             }
         }
     }
diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx
index 660afd4b9..75fc8bf85 100644
--- a/src/client/views/linking/LinkEditor.tsx
+++ b/src/client/views/linking/LinkEditor.tsx
@@ -287,7 +287,7 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
     @observable openDropdown: boolean = false;
     @observable showInfo: boolean = false;
     @computed get infoIcon() { if (this.showInfo) { return "chevron-up"; } return "chevron-down"; }
-    @observable private buttonColor: string = "black";
+    @observable private buttonColor: string = "";
 
 
     //@observable description = this.props.linkDoc.description ? StrCast(this.props.linkDoc.description) : "DESCRIPTION";
@@ -303,7 +303,7 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
         if (LinkManager.currentLink) {
             LinkManager.currentLink.description = value;
             this.buttonColor = "rgb(62, 133, 55)";
-            setTimeout(action(() => this.buttonColor = "black"), 750);
+            setTimeout(action(() => this.buttonColor = ""), 750);
             return true;
         }
     }
@@ -345,7 +345,7 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
                     ></input>
                 </div>
                 <div className="linkEditor-description-add-button"
-                    style={{ backgroundColor: this.buttonColor }}
+                    style={{ background: this.buttonColor }}
                     onPointerDown={this.onDown}>Set</div>
             </div></div>;
     }
diff --git a/src/client/views/nodes/DocumentLinksButton.scss b/src/client/views/nodes/DocumentLinksButton.scss
index 97e714cd5..9328fb96b 100644
--- a/src/client/views/nodes/DocumentLinksButton.scss
+++ b/src/client/views/nodes/DocumentLinksButton.scss
@@ -28,7 +28,13 @@
 }
 
 .documentLinksButton {
-    background-color: $link-color;
+    background-color: black;
+
+    &:hover {
+        background: $main-accent;
+        transform: scale(1.05);
+        cursor: pointer;
+    }
 }
 
 .documentLinksButton-endLink {
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 4713ce447..7899ff0f0 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -181,7 +181,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
 
         const linkButton = <div ref={this._linkButton} style={{ minWidth: 20, minHeight: 20, position: "absolute", left: this.props.Offset?.[0] }}>
             <div className={"documentLinksButton"} style={{
-                backgroundColor: this.props.InMenu ? "black" : "",
+                backgroundColor: this.props.InMenu ? "" : "#add8e6",
                 color: this.props.InMenu ? "white" : "black",
                 width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px", fontWeight: "bold"
             }}
@@ -202,8 +202,8 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                     link : links.length}
 
             </div>
-            {DocumentLinksButton.StartLink && this.props.InMenu && !this.props.StartLink &&
-                DocumentLinksButton.StartLink !== this.props.View ? <div className={"documentLinksButton-endLink"}
+            {this.props.InMenu && !this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View ?
+                <div className={"documentLinksButton-endLink"}
                     style={{
                         width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px",
                         backgroundColor: DocumentLinksButton.StartLink ? "" : "grey",
@@ -218,7 +218,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
         </div>;
 
         return (!links.length) && !this.props.AlwaysOn ? (null) :
-            this.props.InMenu ?
+            this.props.InMenu && (DocumentLinksButton.StartLink || this.props.StartLink) ?
                 <Tooltip title={<><div className="dash-tooltip">{title}</div></>}>
                     {linkButton}
                 </Tooltip> : !!!DocumentLinksButton.EditLink && !this.props.InMenu ?
diff --git a/src/client/views/nodes/FontIconBox.scss b/src/client/views/nodes/FontIconBox.scss
index 5bdafd857..9709e1dbd 100644
--- a/src/client/views/nodes/FontIconBox.scss
+++ b/src/client/views/nodes/FontIconBox.scss
@@ -15,12 +15,17 @@
 
 .menuButton-round {
     border-radius: 100%;
+    background-color: black;
 
     .fontIconBox-label {
         margin-left: -10px; // button padding is 10px;
         bottom: 0;
         position: absolute;
     }
+
+    &:hover {
+        background-color: #aaaaa3;
+    }
 }
 
 .menuButton-square {
diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx
index eff5a4160..c0eb78d98 100644
--- a/src/client/views/nodes/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox.tsx
@@ -63,16 +63,14 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>(
         const color = StrCast(this.layoutDoc.color, this._foregroundColor);
         const backgroundColor = StrCast(this.layoutDoc._backgroundColor, StrCast(this.rootDoc.backgroundColor, this.props.backgroundColor?.(this.rootDoc)));
         const shape = StrCast(this.layoutDoc.iconShape, "round");
-        const button = <>
-            <button className={`menuButton-${shape}`} ref={this._ref} onContextMenu={this.specificContextMenu}
-                style={{ boxShadow: this.layoutDoc.ischecked ? `4px 4px 12px black` : undefined, backgroundColor }}>
-                <div className="menuButton-wrap">
-                    {<FontAwesomeIcon className={`menuButton-icon-${shape}`} icon={StrCast(this.dataDoc.icon, "user") as any} color={color}
-                        size={this.layoutDoc.iconShape === "square" ? "sm" : "lg"} />}
-                    {!label ? (null) : <div className="fontIconBox-label" style={{ color, backgroundColor }}> {label} </div>}
-                </div>
-            </button>
-        </>;
+        const button = <button className={`menuButton-${shape}`} ref={this._ref} onContextMenu={this.specificContextMenu}
+            style={{ boxShadow: this.layoutDoc.ischecked ? `4px 4px 12px black` : undefined, backgroundColor: this.layoutDoc.iconShape === "square" ? backgroundColor : "" }}>
+            <div className="menuButton-wrap">
+                {<FontAwesomeIcon className={`menuButton-icon-${shape}`} icon={StrCast(this.dataDoc.icon, "user") as any} color={color}
+                    size={this.layoutDoc.iconShape === "square" ? "sm" : "lg"} />}
+                {!label ? (null) : <div className="fontIconBox-label" style={{ color, backgroundColor }}> {label} </div>}
+            </div>
+        </button>;
         return !this.layoutDoc.toolTip ? button :
             <Tooltip title={<div className="dash-tooltip">{StrCast(this.layoutDoc.toolTip)}</div>}>
                 {button}
-- 
cgit v1.2.3-70-g09d2


From e83fd812ed3798a7e7c22ad132a2f9e8dccaa76c Mon Sep 17 00:00:00 2001
From: Andy Rickert <andrew_rickert@brown.edu>
Date: Tue, 4 Aug 2020 22:05:30 -0400
Subject: changes

---
 src/client/documents/Documents.ts                  |  14 +-
 src/client/util/CurrentUserUtils.ts                |  12 +-
 src/client/views/SearchDocBox.tsx                  | 428 ----------------
 .../views/collections/CollectionSchemaCells.tsx    |  84 +++-
 .../views/collections/CollectionSchemaHeaders.tsx  |   8 +-
 .../views/collections/CollectionSchemaView.scss    |   2 +-
 src/client/views/collections/CollectionSubView.tsx |  53 +-
 src/client/views/collections/SchemaTable.tsx       |  47 +-
 .../collectionFreeForm/PropertiesView.tsx          |   2 +-
 src/client/views/nodes/DocumentContentsView.tsx    |   3 +-
 src/client/views/nodes/LabelBox.tsx                |   2 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |   1 -
 src/client/views/search/SearchBox.tsx              | 419 +++++-----------
 src/client/views/search/SearchItem.scss            | 186 -------
 src/client/views/search/SearchItem.tsx             | 556 ---------------------
 15 files changed, 300 insertions(+), 1517 deletions(-)
 delete mode 100644 src/client/views/SearchDocBox.tsx
 delete mode 100644 src/client/views/search/SearchItem.scss
 delete mode 100644 src/client/views/search/SearchItem.tsx

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index e6eaaad60..b809a73b7 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -22,8 +22,7 @@ import { LinkManager } from "../util/LinkManager";
 import { Scripting } from "../util/Scripting";
 import { UndoManager } from "../util/UndoManager";
 import { DocumentType } from "./DocumentTypes";
-import { SearchItem } from "../views/search/SearchItem";
-import { SearchBox, filterData } from "../views/search/SearchBox";
+import { SearchBox } from "../views/search/SearchBox";
 import { CollectionDockingView } from "../views/collections/CollectionDockingView";
 import { CollectionView, CollectionViewType } from "../views/collections/CollectionView";
 import { ContextMenu } from "../views/ContextMenu";
@@ -48,7 +47,6 @@ import { VideoBox } from "../views/nodes/VideoBox";
 import { WebBox } from "../views/nodes/WebBox";
 import { PresElementBox } from "../views/presentationview/PresElementBox";
 import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo";
-import { DocumentType } from "./DocumentTypes";
 import { Networking } from "../Network";
 import { Upload } from "../../server/SharedMediaTypes";
 const path = require('path');
@@ -191,8 +189,7 @@ export interface DocumentOptions {
     flexDirection?: "unset" | "row" | "column" | "row-reverse" | "column-reverse";
     selectedIndex?: number;
     syntaxColor?: string; // can be applied to text for syntax highlighting all matches in the text
-    searchQuery?: string, // for quersyBox
-    filterQuery?: filterData,
+    searchQuery?: string; // for quersyBox
     linearViewIsExpanded?: boolean; // is linear view expanded
     border?: string; //for searchbox
     hovercolor?: string;
@@ -316,9 +313,6 @@ export namespace Docs {
             [DocumentType.PRESELEMENT, {
                 layout: { view: PresElementBox, dataField: defaultDataKey }
             }],
-            [DocumentType.SEARCHITEM, {
-                layout: { view: SearchItem, dataField: defaultDataKey }
-            }],
             [DocumentType.INK, {
                 layout: { view: InkingStroke, dataField: defaultDataKey },
                 options: { backgroundColor: "transparent" }
@@ -803,10 +797,6 @@ export namespace Docs {
             return InstanceFromProto(Prototypes.get(DocumentType.PRESELEMENT), undefined, { ...(options || {}) });
         }
 
-        export function SearchItemBoxDocument(options?: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.SEARCHITEM), undefined, { ...(options || {}) });
-        }
-
         export function DockDocument(documents: Array<Doc>, config: string, options: DocumentOptions, id?: string) {
             const inst = InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id);
             Doc.GetProto(inst).data = new List<Doc>(documents);
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 84cd4823b..cd8c09a0e 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -543,7 +543,7 @@ export class CurrentUserUtils {
                     btn.color = "white";
                     btn._backgroundColor = "";
                 }));
-            })
+            });
         });
         return doc.menuStack as Doc;
     }
@@ -761,16 +761,6 @@ export class CurrentUserUtils {
         }
     }
 
-    static setupSidebarContainer(doc: Doc) {
-        if (doc["sidebar"] === undefined) {
-            const sidebarContainer = new Doc();
-            sidebarContainer._chromeStatus = "disabled";
-            sidebarContainer.onClick = ScriptField.MakeScript("freezeSidebar()");
-            doc["sidebar"] = new PrefetchProxy(sidebarContainer);
-        }
-        return doc["sidebar"] as Doc;
-    }
-
     // setup the list of sidebar mode buttons which determine what is displayed in the sidebar
     static async setupSidebarButtons(doc: Doc) {
         await CurrentUserUtils.setupToolsBtnPanel(doc);
diff --git a/src/client/views/SearchDocBox.tsx b/src/client/views/SearchDocBox.tsx
deleted file mode 100644
index 084f952a3..000000000
--- a/src/client/views/SearchDocBox.tsx
+++ /dev/null
@@ -1,428 +0,0 @@
-import { library } from "@fortawesome/fontawesome-svg-core";
-import { faBullseye, faLink } from "@fortawesome/free-solid-svg-icons";
-import { action, computed, observable, runInAction } from "mobx";
-import { observer } from "mobx-react";
-//import "./SearchBoxDoc.scss";
-import { Doc, DocListCast } from "../../fields/Doc";
-import { Id } from "../../fields/FieldSymbols";
-import { BoolCast, Cast, NumCast, StrCast } from "../../fields/Types";
-import { returnFalse, returnZero } from "../../Utils";
-import { Docs } from "../documents/Documents";
-import { SearchUtil } from "../util/SearchUtil";
-import { EditableView } from "./EditableView";
-import { ContentFittingDocumentView } from "./nodes/ContentFittingDocumentView";
-import { FieldView, FieldViewProps } from "./nodes/FieldView";
-import { FilterBox } from "./search/FilterBox";
-import { SearchItem } from "./search/SearchItem";
-import React = require("react");
-
-export interface RecProps {
-    documents: { preview: Doc, similarity: number }[];
-    node: Doc;
-
-}
-
-library.add(faBullseye, faLink);
-export const keyPlaceholder = "Query";
-
-@observer
-export class SearchDocBox extends React.Component<FieldViewProps> {
-
-    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(SearchDocBox, fieldKey); }
-
-    // @observable private _display: boolean = false;
-    @observable private _pageX: number = 0;
-    @observable private _pageY: number = 0;
-    @observable private _width: number = 0;
-    @observable private _height: number = 0;
-    @observable.shallow private _docViews: JSX.Element[] = [];
-    // @observable private _documents: { preview: Doc, score: number }[] = [];
-    private previewDocs: Doc[] = [];
-
-    constructor(props: FieldViewProps) {
-        super(props);
-        this.editingMetadata = this.editingMetadata || false;
-        //SearchBox.Instance = this;
-        this.resultsScrolled = this.resultsScrolled.bind(this);
-    }
-
-
-    @computed
-    private get editingMetadata() {
-        return BoolCast(this.props.Document.editingMetadata);
-    }
-
-    private set editingMetadata(value: boolean) {
-        this.props.Document.editingMetadata = value;
-    }
-
-    static readonly buffer = 20;
-
-    componentDidMount() {
-        runInAction(() => {
-            this.query = StrCast(this.props.Document.searchText);
-            this.content = (Docs.Create.TreeDocument(DocListCast(Doc.GetProto(this.props.Document).data), { _width: 200, _height: 400, _chromeStatus: "disabled", title: `Search Docs:` + this.query }));
-
-        });
-        if (this.inputRef.current) {
-            this.inputRef.current.focus();
-            runInAction(() => {
-                this._searchbarOpen = true;
-            });
-        }
-    }
-
-    @observable
-    private content: Doc | undefined;
-
-    @action
-    updateKey = async (newKey: string) => {
-        this.query = newKey;
-        if (newKey.length > 1) {
-            const newdocs = await this.getAllResults(this.query);
-            const things = newdocs.docs;
-            runInAction(() => {
-                this.content = Docs.Create.TreeDocument(things, { _width: 200, _height: 400, _chromeStatus: "disabled", title: `Search Docs:` + this.query });
-            });
-        }
-
-
-        //this.keyRef.current && this.keyRef.current.setIsFocused(false);
-        //this.query.length === 0 && (this.query = keyPlaceholder);
-        return true;
-    }
-
-    @computed
-    public get query() {
-        return StrCast(this.props.Document.query);
-    }
-
-    public set query(value: string) {
-        this.props.Document.query = value;
-    }
-
-    @observable private _searchString: string = "";
-    @observable private _resultsOpen: boolean = false;
-    @observable private _searchbarOpen: boolean = false;
-    @observable private _results: [Doc, string[], string[]][] = [];
-    private _resultsSet = new Map<Doc, number>();
-    @observable private _openNoResults: boolean = false;
-    @observable private _visibleElements: JSX.Element[] = [];
-
-    private resultsRef = React.createRef<HTMLDivElement>();
-    public inputRef = React.createRef<HTMLInputElement>();
-
-    private _isSearch: ("search" | "placeholder" | undefined)[] = [];
-    private _numTotalResults = -1;
-    private _endIndex = -1;
-
-
-    private _maxSearchIndex: number = 0;
-    private _curRequest?: Promise<any> = undefined;
-
-    @action
-    getViews = async (doc: Doc) => {
-        const results = await SearchUtil.GetViewsOfDocument(doc);
-        let toReturn: Doc[] = [];
-        await runInAction(() => {
-            toReturn = results;
-        });
-        return toReturn;
-    }
-
-    @action.bound
-    onChange(e: React.ChangeEvent<HTMLInputElement>) {
-        this._searchString = e.target.value;
-
-        this._openNoResults = false;
-        this._results = [];
-        this._resultsSet.clear();
-        this._visibleElements = [];
-        this._numTotalResults = -1;
-        this._endIndex = -1;
-        this._curRequest = undefined;
-        this._maxSearchIndex = 0;
-    }
-
-    enter = async (e: React.KeyboardEvent) => {
-        if (e.key === "Enter") {
-            const newdocs = await this.getAllResults(this.query);
-            this.content = Docs.Create.TreeDocument(newdocs.docs, { _width: 200, _height: 400, _chromeStatus: "disabled", title: `Search Docs: "Results"` });
-        }
-    }
-
-
-    @action
-    submitSearch = async () => {
-        let query = this._searchString;
-        query = FilterBox.Instance.getFinalQuery(query);
-        this._results = [];
-        this._resultsSet.clear();
-        this._isSearch = [];
-        this._visibleElements = [];
-        FilterBox.Instance.closeFilter();
-
-        //if there is no query there should be no result
-        if (query === "") {
-            return;
-        }
-        else {
-            this._endIndex = 12;
-            this._maxSearchIndex = 0;
-            this._numTotalResults = -1;
-            await this.getResults(query);
-        }
-
-        runInAction(() => {
-            this._resultsOpen = true;
-            this._searchbarOpen = true;
-            this._openNoResults = true;
-            this.resultsScrolled();
-        });
-    }
-
-    getAllResults = async (query: string) => {
-        return SearchUtil.Search(query, true, { fq: this.filterQuery, start: 0, rows: 10000000 });
-    }
-
-    private get filterQuery() {
-        const types = FilterBox.Instance.filterTypes;
-        const includeDeleted = FilterBox.Instance.getDataStatus();
-        return "NOT baseProto_b:true" + (includeDeleted ? "" : " AND NOT deleted_b:true") + (types ? ` AND (${types.map(type => `({!join from=id to=proto_i}type_t:"${type}" AND NOT type_t:*) OR type_t:"${type}" OR type_t:"extension"`).join(" ")})` : "");
-    }
-
-
-    private NumResults = 25;
-    private lockPromise?: Promise<void>;
-    getResults = async (query: string) => {
-        if (this.lockPromise) {
-            await this.lockPromise;
-        }
-        this.lockPromise = new Promise(async res => {
-            while (this._results.length <= this._endIndex && (this._numTotalResults === -1 || this._maxSearchIndex < this._numTotalResults)) {
-                this._curRequest = SearchUtil.Search(query, true, { fq: this.filterQuery, start: this._maxSearchIndex, rows: this.NumResults, hl: true, "hl.fl": "*" }).then(action(async (res: SearchUtil.DocSearchResult) => {
-
-                    // happens at the beginning
-                    if (res.numFound !== this._numTotalResults && this._numTotalResults === -1) {
-                        this._numTotalResults = res.numFound;
-                    }
-
-                    const highlighting = res.highlighting || {};
-                    const highlightList = res.docs.map(doc => highlighting[doc[Id]]);
-                    const lines = new Map<string, string[]>();
-                    res.docs.map((doc, i) => lines.set(doc[Id], res.lines[i]));
-                    const docs = await Promise.all(res.docs.map(async doc => (await Cast(doc.extendsDoc, Doc)) || doc));
-                    const highlights: typeof res.highlighting = {};
-                    docs.forEach((doc, index) => highlights[doc[Id]] = highlightList[index]);
-                    const filteredDocs = FilterBox.Instance.filterDocsByType(docs);
-                    runInAction(() => {
-                        // this._results.push(...filteredDocs);
-                        filteredDocs.forEach(doc => {
-                            const index = this._resultsSet.get(doc);
-                            const highlight = highlights[doc[Id]];
-                            const line = lines.get(doc[Id]) || [];
-                            const hlights = highlight ? Object.keys(highlight).map(key => key.substring(0, key.length - 2)) : [];
-                            if (index === undefined) {
-                                this._resultsSet.set(doc, this._results.length);
-                                this._results.push([doc, hlights, line]);
-                            } else {
-                                this._results[index][1].push(...hlights);
-                                this._results[index][2].push(...line);
-                            }
-                        });
-                    });
-
-                    this._curRequest = undefined;
-                }));
-                this._maxSearchIndex += this.NumResults;
-
-                await this._curRequest;
-            }
-            this.resultsScrolled();
-            res();
-        });
-        return this.lockPromise;
-    }
-
-    collectionRef = React.createRef<HTMLSpanElement>();
-    startDragCollection = async () => {
-        const res = await this.getAllResults(FilterBox.Instance.getFinalQuery(this._searchString));
-        const filtered = FilterBox.Instance.filterDocsByType(res.docs);
-        const docs = filtered.map(doc => {
-            const isProto = Doc.GetT(doc, "isPrototype", "boolean", true);
-            if (isProto) {
-                return Doc.MakeDelegate(doc);
-            } else {
-                return Doc.MakeAlias(doc);
-            }
-        });
-        let x = 0;
-        let y = 0;
-        for (const doc of docs.map(d => Doc.Layout(d))) {
-            doc.x = x;
-            doc.y = y;
-            const size = 200;
-            const aspect = NumCast(doc._nativeHeight) / NumCast(doc._nativeWidth, 1);
-            if (aspect > 1) {
-                doc._height = size;
-                doc._width = size / aspect;
-            } else if (aspect > 0) {
-                doc._width = size;
-                doc._height = size * aspect;
-            } else {
-                doc._width = size;
-                doc._height = size;
-            }
-            x += 250;
-            if (x > 1000) {
-                x = 0;
-                y += 300;
-            }
-        }
-        //return Docs.Create.TreeDocument(docs, { _width: 200, _height: 400, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` });
-        return Docs.Create.QueryDocument({ _width: 200, _height: 400, searchText: this._searchString, title: `Query Docs: "${this._searchString}"` });
-    }
-
-    @action.bound
-    openSearch(e: React.SyntheticEvent) {
-        e.stopPropagation();
-        this._openNoResults = false;
-        FilterBox.Instance.closeFilter();
-        this._resultsOpen = true;
-        this._searchbarOpen = true;
-        FilterBox.Instance._pointerTime = e.timeStamp;
-    }
-
-    @action.bound
-    closeSearch = () => {
-        FilterBox.Instance.closeFilter();
-        this.closeResults();
-        this._searchbarOpen = false;
-    }
-
-    @action.bound
-    closeResults() {
-        this._resultsOpen = false;
-        this._results = [];
-        this._resultsSet.clear();
-        this._visibleElements = [];
-        this._numTotalResults = -1;
-        this._endIndex = -1;
-        this._curRequest = undefined;
-    }
-
-    @action
-    resultsScrolled = (e?: React.UIEvent<HTMLDivElement>) => {
-        if (!this.resultsRef.current) return;
-        const scrollY = e ? e.currentTarget.scrollTop : this.resultsRef.current ? this.resultsRef.current.scrollTop : 0;
-        const itemHght = 53;
-        const startIndex = Math.floor(Math.max(0, scrollY / itemHght));
-        const endIndex = Math.ceil(Math.min(this._numTotalResults - 1, startIndex + (this.resultsRef.current.getBoundingClientRect().height / itemHght)));
-
-        this._endIndex = endIndex === -1 ? 12 : endIndex;
-
-        if ((this._numTotalResults === 0 || this._results.length === 0) && this._openNoResults) {
-            this._visibleElements = [<div className="no-result">No Search Results</div>];
-            return;
-        }
-
-        if (this._numTotalResults <= this._maxSearchIndex) {
-            this._numTotalResults = this._results.length;
-        }
-
-        // only hit right at the beginning
-        // visibleElements is all of the elements (even the ones you can't see)
-        else if (this._visibleElements.length !== this._numTotalResults) {
-            // undefined until a searchitem is put in there
-            this._visibleElements = Array<JSX.Element>(this._numTotalResults === -1 ? 0 : this._numTotalResults);
-            // indicates if things are placeholders
-            this._isSearch = Array<undefined>(this._numTotalResults === -1 ? 0 : this._numTotalResults);
-        }
-
-        for (let i = 0; i < this._numTotalResults; i++) {
-            //if the index is out of the window then put a placeholder in
-            //should ones that have already been found get set to placeholders?
-            if (i < startIndex || i > endIndex) {
-                if (this._isSearch[i] !== "placeholder") {
-                    this._isSearch[i] = "placeholder";
-                    this._visibleElements[i] = <div className="searchBox-placeholder" key={`searchBox-placeholder-${i}`}>Loading...</div>;
-                }
-            }
-            else {
-                if (this._isSearch[i] !== "search") {
-                    let result: [Doc, string[], string[]] | undefined = undefined;
-                    if (i >= this._results.length) {
-                        this.getResults(this._searchString);
-                        if (i < this._results.length) result = this._results[i];
-                        if (result) {
-                            const highlights = Array.from([...Array.from(new Set(result[1]).values())]);
-                            this._visibleElements[i] = <SearchItem doc={result[0]} query={this._searchString} key={result[0][Id]} lines={result[2]} highlighting={highlights} />;
-                            this._isSearch[i] = "search";
-                        }
-                    }
-                    else {
-                        result = this._results[i];
-                        if (result) {
-                            const highlights = Array.from([...Array.from(new Set(result[1]).values())]);
-                            this._visibleElements[i] = <SearchItem doc={result[0]} query={this._searchString} key={result[0][Id]} lines={result[2]} highlighting={highlights} />;
-                            this._isSearch[i] = "search";
-                        }
-                    }
-                }
-            }
-        }
-        if (this._maxSearchIndex >= this._numTotalResults) {
-            this._visibleElements.length = this._results.length;
-            this._isSearch.length = this._results.length;
-        }
-    }
-
-    @computed
-    get resFull() { return this._numTotalResults <= 8; }
-
-    @computed
-    get resultHeight() { return this._numTotalResults * 70; }
-
-    render() {
-        const isEditing = this.editingMetadata;
-        return !this.content ? (null) : (
-            <div style={{ pointerEvents: "all" }}>
-                <ContentFittingDocumentView {...this.props}
-                    Document={this.content}
-                    rootSelected={returnFalse}
-                    bringToFront={returnFalse}
-                    ContainingCollectionDoc={undefined}
-                    ContainingCollectionView={undefined}
-                    NativeWidth={returnZero}
-                    NativeHeight={returnZero}
-                    parentActive={this.props.active}
-                    ScreenToLocalTransform={this.props.ScreenToLocalTransform}>
-                </ContentFittingDocumentView>
-                <div
-                    style={{
-                        position: "absolute",
-                        right: 0,
-                        width: 20,
-                        height: 20,
-                        background: "black",
-                        pointerEvents: "all",
-                        opacity: 1,
-                        transition: "0.4s opacity ease",
-                        zIndex: 99,
-                        top: 0,
-                    }}
-                    title={"Add Metadata"}
-                    onClick={action(() => this.editingMetadata = !this.editingMetadata)}
-                />
-                <div className="editableclass" onKeyPress={this.enter} style={{ opacity: isEditing ? 1 : 0, pointerEvents: isEditing ? "auto" : "none", transition: "0.4s opacity ease", position: "absolute", top: 0, left: 0, height: 20, width: "-webkit-fill-available" }}>
-                    <EditableView
-                        contents={this.query}
-                        SetValue={this.updateKey}
-                        GetValue={() => ""}
-                    />
-                </div>
-            </div >
-        );
-    }
-
-}
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index ecd20eb06..6e19bb029 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -242,7 +242,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
         //     </div>
         // );   
         trace();
-        let positions = [];
+        const positions = [];
         if (StrCast(this.props.Document._searchString) !== "") {
             const cfield = ComputedField.WithoutComputed(() => FieldValue(props.Document[props.fieldKey]));
             let term = "";
@@ -257,7 +257,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
                     term = String(NumCast(cfield));
                 }
             }
-            let search = StrCast(this.props.Document._searchString)
+            let search = StrCast(this.props.Document._searchString);
             let start = term.indexOf(search) as number;
             let tally = 0;
             if (start !== -1) {
@@ -873,3 +873,83 @@ export class CollectionSchemaCheckboxCell extends CollectionSchemaCell {
         );
     }
 }
+
+
+@observer
+export class CollectionSchemaButtons extends CollectionSchemaCell {
+
+    render() {
+        // const reference = React.createRef<HTMLDivElement>();
+        // const onItemDown = (e: React.PointerEvent) => {
+        //     (!this.props.CollectionView || !this.props.CollectionView.props.isSelected() ? undefined :
+        //         SetupDrag(reference, () => this._document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e));
+        // };
+        let doc = this.props.rowProps.original;
+        let buttons = <div style={{
+            paddingTop: 8,
+            paddingLeft: 3,
+        }}><button onClick={() => {
+            console.log(doc);
+            console.log(doc.searchMatch);
+            doc.searchMatch = false;
+            console.log(doc.searchMatch);
+            setTimeout(() => doc.searchMatch = true, 0);
+            console.log(doc.searchMatch);
+            doc.searchIndex = NumCast(doc.searchIndex);
+        }} style={{ padding: 2, left: 77 }}>
+                <FontAwesomeIcon icon="arrow-up" size="sm" />
+            </button>
+            <button onClick={() => {
+                {
+                    console.log(doc);
+                    console.log(doc.searchMatch2);
+                    doc.searchMatch2 = false;
+                    console.log(doc.searchMatch2);
+                    setTimeout(() => doc.searchMatch2 = true, 0);
+                    console.log(doc.searchMatch2);
+                    doc.searchIndex = NumCast(doc.searchIndex);
+                }
+            }} style={{ padding: 2 }}>
+                <FontAwesomeIcon icon="arrow-down" size="sm" />
+            </button></div>;
+        const type = StrCast(doc.type);
+        console.log(StrCast(doc.type));
+        if (type === "pdf") {
+            buttons = <div><button
+                style={{
+                    position: "relative",
+                    height: 30,
+                    width: 28,
+                    left: 1,
+                }}
+
+                onClick={() => {
+                    console.log(doc);
+                    console.log(doc.searchMatch);
+                    doc.searchMatch = false;
+                    console.log(doc.searchMatch);
+                    setTimeout(() => doc.searchMatch = true, 0);
+                    console.log(doc.searchMatch);
+                    doc.searchIndex = NumCast(doc.searchIndex);
+                }}>
+                <FontAwesomeIcon icon="arrow-down" size="sm" />
+            </button></div >
+        }
+        else if (type !== "rtf") {
+            console.log("sad");
+            buttons = undefined;
+        }
+
+        if (BoolCast(this.props.Document._searchDoc) === true) {
+
+        }
+        else {
+            buttons = undefined;
+        }
+
+        return (
+            <div> {buttons}</div>
+        );
+    }
+}
+
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index 5d7ab2c61..e65adcf76 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -302,7 +302,7 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
     @action
     onSelect = (key: string): void => {
         if (key.slice(0, this._key.length) === this._key && this._key !== key) {
-            let filter = key.slice(this._key.length - key.length);
+            const filter = key.slice(this._key.length - key.length);
             this.props.onSelect(this._key, this._key, this.props.addNew, filter);
         }
         else {
@@ -395,12 +395,10 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
 
     renderFilterOptions = (): JSX.Element[] | JSX.Element => {
         if (!this._isOpen) return <></>;
-
         const keyOptions: string[] = [];
-        console.log(this._searchTerm.slice(this._key.length))
-        let temp = this._searchTerm.slice(this._key.length);
+        const temp = this._searchTerm.slice(this._key.length);
         this.props.docs?.forEach((doc) => {
-            let key = StrCast(doc[this._key]);
+            const key = StrCast(doc[this._key]);
             if (keyOptions.includes(key) === false && key.includes(temp)) {
                 keyOptions.push(key);
             }
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 93878d799..2dcd6d6c0 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -93,7 +93,7 @@
     }
 
     .rt-tbody {
-        width: calc(100% - 2px);
+        width: 100%;
         direction: rtl;
         overflow: visible;
     }
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 88241f519..bf3129a8a 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -130,9 +130,60 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
             let childDocs = viewSpecScript ? docs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result) : docs;
 
             const searchDocs = DocListCast(this.props.Document._searchDocs);
+            // if (searchDocs !== undefined && searchDocs.length > 0) {
+            //     let newdocs: Doc[] = [];
+            //     childDocs.forEach((el) => {
+            //         searchDocs.includes(el) ? newdocs.push(el) : undefined;
+            //     });
+            //     childDocs = newdocs;
+            // }
+
+            let docsforFilter: Doc[] = childDocs;
             if (searchDocs !== undefined && searchDocs.length > 0) {
-                childDocs = searchDocs;
+                docsforFilter = [];
+                // let newdocs: Doc[] = [];
+                // let newarray: Doc[] = [];
+                //while (childDocs.length > 0) {
+                //newarray = [];
+                childDocs.forEach((d) => {
+                    if (d.data !== undefined) {
+                        console.log(d);
+                        let newdocs = DocListCast(d.data);
+                        if (newdocs.length > 0) {
+                            let vibecheck = false;
+
+                            let newarray: Doc[] = [];
+
+                            while (newdocs.length > 0) {
+                                newarray = [];
+                                newdocs.forEach((t) => {
+                                    if (d.data !== undefined) {
+                                        let newdocs = DocListCast(t.data);
+                                        newdocs.forEach((newdoc) => {
+                                            newarray.push(newdoc);
+                                        });
+                                    }
+                                    if (searchDocs.includes(t)) {
+                                        vibecheck = true;
+                                    }
+                                });
+                                newdocs = newarray;
+                            }
+                            if (vibecheck === true) {
+                                docsforFilter.push(d);
+                            }
+                        }
+                    }
+                    if (searchDocs.includes(d)) {
+                        docsforFilter.push(d);
+                    }
+                });
+                //childDocs = newarray;
+                //}
             }
+            childDocs = docsforFilter;
+
+
             const docFilters = this.docFilters();
             const docRangeFilters = this.props.ignoreFields?.includes("_docRangeFilters") ? [] : Cast(this.props.Document._docRangeFilters, listSpec("string"), []);
 
diff --git a/src/client/views/collections/SchemaTable.tsx b/src/client/views/collections/SchemaTable.tsx
index 9d02807fd..8b7717ad1 100644
--- a/src/client/views/collections/SchemaTable.tsx
+++ b/src/client/views/collections/SchemaTable.tsx
@@ -19,7 +19,7 @@ import { undoBatch } from "../../util/UndoManager";
 import { COLLECTION_BORDER_WIDTH } from '../../views/globalCssVariables.scss';
 import { ContextMenu } from "../ContextMenu";
 import '../DocumentDecorations.scss';
-import { CellProps, CollectionSchemaCell, CollectionSchemaCheckboxCell, CollectionSchemaDocCell, CollectionSchemaNumberCell, CollectionSchemaStringCell, CollectionSchemaImageCell, CollectionSchemaListCell, CollectionSchemaDateCell } from "./CollectionSchemaCells";
+import { CellProps, CollectionSchemaCell, CollectionSchemaCheckboxCell, CollectionSchemaDocCell, CollectionSchemaNumberCell, CollectionSchemaStringCell, CollectionSchemaImageCell, CollectionSchemaListCell, CollectionSchemaDateCell, CollectionSchemaButtons } from "./CollectionSchemaCells";
 import { CollectionSchemaAddColumnHeader, KeysDropdown } from "./CollectionSchemaHeaders";
 import { MovableColumn, MovableRow } from "./CollectionSchemaMovableTableHOC";
 import "./CollectionSchemaView.scss";
@@ -160,7 +160,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         const focusedCol = this._focusedCell.col;
         const isEditable = !this.props.headerIsEditing;
 
-        if (this.childDocs.reduce((found, doc) => found || doc.type === "collection", false)) {
+        if (this.childDocs.reduce((found, doc) => found || doc.type === "nnnnn", false)) {
             columns.push(
                 {
                     expander: true,
@@ -283,12 +283,34 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             Header: <CollectionSchemaAddColumnHeader createColumn={this.createColumn} />,
             accessor: (doc: Doc) => 0,
             id: "add",
-            Cell: (rowProps: CellInfo) => <div> <button onClick={(e) => this.nextHighlight(e, this.props.Document)} style={{ padding: 2, left: 77 }}>
-                <FontAwesomeIcon icon="arrow-up" size="sm" />
-            </button>
-                <button onClick={(e) => this.nextHighlight2(e, this.props.Document)} style={{ padding: 2, left: 87 }}>
-                    <FontAwesomeIcon icon="arrow-down" size="sm" />
-                </button></div>,
+            Cell: (rowProps: CellInfo) => {
+                const rowIndex = rowProps.index;
+                const columnIndex = this.props.columns.map(c => c.heading).indexOf(rowProps.column.id!);
+                const isFocused = focusedRow === rowIndex && focusedCol === columnIndex && tableIsFocused;
+                const props: CellProps = {
+                    row: rowIndex,
+                    col: columnIndex,
+                    rowProps: rowProps,
+                    isFocused: isFocused,
+                    changeFocusedCellByIndex: this.changeFocusedCellByIndex,
+                    CollectionView: this.props.CollectionView,
+                    ContainingCollection: this.props.ContainingCollectionView,
+                    Document: this.props.Document,
+                    fieldKey: this.props.fieldKey,
+                    renderDepth: this.props.renderDepth,
+                    addDocTab: this.props.addDocTab,
+                    pinToPres: this.props.pinToPres,
+                    moveDocument: this.props.moveDocument,
+                    setIsEditing: this.setCellIsEditing,
+                    isEditable: isEditable,
+                    setPreviewDoc: this.props.setPreviewDoc,
+                    setComputed: this.setComputed,
+                    getField: this.getField,
+                    showDoc: this.showDoc,
+                };
+
+                return <CollectionSchemaButtons {...props} />;
+            },
             width: 28,
             resizable: false
         });
@@ -301,16 +323,17 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     nextHighlight = (e: React.MouseEvent, doc: Doc) => {
         e.preventDefault();
         e.stopPropagation();
-
         doc.searchMatch = false;
+        console.log(doc.searchMatch);
         setTimeout(() => doc.searchMatch = true, 0);
+        console.log(doc.searchMatch);
+
         doc.searchIndex = NumCast(doc.searchIndex);
     }
 
     @action
-    nextHighlight2 = (e: React.MouseEvent, doc: Doc) => {
-        e.preventDefault();
-        e.stopPropagation();
+    nextHighlight2 = (doc: Doc) => {
+
         doc.searchMatch2 = false;
         setTimeout(() => doc.searchMatch2 = true, 0);
         doc.searchIndex = NumCast(doc.searchIndex);
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index f5e0cd077..031dbf884 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -539,7 +539,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     getField(key: string) {
         //if (this.selectedDoc) {
-        return Field.toString(this.selectedDoc[key] as Field);
+        return Field.toString(this.selectedDoc![key] as Field);
         // } else {
         //     return undefined as Opt<string>;
         // }
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index c724ba50b..1282bbee5 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -25,7 +25,6 @@ import { KeyValueBox } from "./KeyValueBox";
 import { PDFBox } from "./PDFBox";
 import { PresBox } from "./PresBox";
 import { SearchBox } from "../search/SearchBox";
-import { SearchItem } from "../search/SearchItem"
 import { ColorBox } from "./ColorBox";
 import { DashWebRTCVideo } from "../webcam/DashWebRTCVideo";
 import { LinkAnchorBox } from "./LinkAnchorBox";
@@ -192,7 +191,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
                 components={{
                     FormattedTextBox, ImageBox, DirectoryImportBox, FontIconBox, LabelBox, SliderBox, FieldView,
                     CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValueBox,
-                    PDFBox, VideoBox, AudioBox, PresBox, YoutubeBox, PresElementBox, SearchBox, SearchItem,
+                    PDFBox, VideoBox, AudioBox, PresBox, YoutubeBox, PresElementBox, SearchBox,
                     ColorBox, DashWebRTCVideo, LinkAnchorBox, InkingStroke, DocHolderBox, LinkBox, ScriptingBox,
                     ScreenshotBox, HTMLtag, ComparisonBox
                 }}
diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx
index 302d66cc5..10a164158 100644
--- a/src/client/views/nodes/LabelBox.tsx
+++ b/src/client/views/nodes/LabelBox.tsx
@@ -70,7 +70,7 @@ export class LabelBox extends ViewBoxBaseComponent<FieldViewProps, LabelDocument
         const missingParams = params?.filter(p => !this.paramsDoc[p]);
         params?.map(p => DocListCast(this.paramsDoc[p])); // bcz: really hacky form of prefetching ... 
         return (
-            <div className="labelBox-outerDiv" onClick={() => runInAction(() => { this.clicked = !this.clicked; this.clicked ? this.backColor = StrCast(this.layoutDoc.hovercolor) : this.backColor = "unset" })} onMouseLeave={() => runInAction(() => { !this.clicked ? this.backColor = "unset" : null })}
+            <div className="labelBox-outerDiv" onClick={() => runInAction(() => { this.clicked = !this.clicked; this.clicked ? this.backColor = StrCast(this.layoutDoc.hovercolor) : this.backColor = "unset"; })} onMouseLeave={() => runInAction(() => { !this.clicked ? this.backColor = "unset" : null; })}
                 onMouseOver={() => runInAction(() => { this.backColor = StrCast(this.layoutDoc.hovercolor); })} ref={this.createDropTarget} onContextMenu={this.specificContextMenu}
                 style={{ boxShadow: this.layoutDoc.opacity ? StrCast(this.layoutDoc.boxShadow) : "" }}>
                 <div className="labelBox-mainButton" style={{
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 79cf5c5fd..b21596493 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -309,7 +309,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             this._searchIndex = ++this._searchIndex > flattened.length - 1 ? 0 : this._searchIndex;
             this._editorView.dispatch(tr.setSelection(new TextSelection(tr.doc.resolve(flattened[lastSel].from), tr.doc.resolve(flattened[lastSel].to))).scrollIntoView());
 
-            console.log(this._searchIndex, length);
             if (this._searchIndex > 1) {
                 this._searchIndex += -2;
             }
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index b76955815..acdd8d047 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -39,14 +39,6 @@ export enum Keys {
     TEXT = "text"
 }
 
-export interface filterData {
-    deletedDocsStatus: boolean;
-    authorFieldStatus: boolean;
-    titleFieldStatus: boolean;
-    basicWordStatus: boolean;
-    icons: string[];
-}
-
 type SearchBoxDocument = makeInterface<[typeof documentSchema, typeof searchSchema]>;
 const SearchBoxDocument = makeInterface(documentSchema, searchSchema);
 
@@ -89,55 +81,16 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
     @observable private newAssign: boolean = true;
 
     constructor(props: any) {
-
         super(props);
         SearchBox.Instance = this;
-        if (!_scriptingGlobals.hasOwnProperty("handleNodeChange")) {
-            Scripting.addGlobal(this.handleNodeChange);
-        }
-        if (!_scriptingGlobals.hasOwnProperty("handleKeyChange")) {
-            Scripting.addGlobal(this.handleKeyChange);
-        }
-        if (!_scriptingGlobals.hasOwnProperty("handleWordQueryChange")) {
-            Scripting.addGlobal(this.handleWordQueryChange);
-        }
-        if (!_scriptingGlobals.hasOwnProperty("updateIcon")) {
-            Scripting.addGlobal(this.updateIcon);
-        }
-        if (!_scriptingGlobals.hasOwnProperty("updateTitleStatus")) {
-            Scripting.addGlobal(this.updateTitleStatus);
-        }
-        if (!_scriptingGlobals.hasOwnProperty("updateAuthorStatus")) {
-            Scripting.addGlobal(this.updateAuthorStatus);
-        }
-        if (!_scriptingGlobals.hasOwnProperty("updateDeletedStatus")) {
-            Scripting.addGlobal(this.updateDeletedStatus);
-        }
-
-
         this.resultsScrolled = this.resultsScrolled.bind(this);
 
-        // new PrefetchProxy(Docs.Create.SearchItemBoxDocument({
-        //     title: "search item template",
-        //     backgroundColor: "transparent", _xMargin: 5, _height: 46, isTemplateDoc: true, isTemplateForField: "data"
-        // }));
-
-
-        // if (!this.searchItemTemplate) { // create exactly one presElmentBox template to use by any and all presentations.
-        //     Doc.UserDoc().searchItemTemplate = new PrefetchProxy(Docs.Create.SearchItemBoxDocument({ title: "search item template", backgroundColor: "transparent", _xMargin: 5, _height: 46, isTemplateDoc: true, isTemplateForField: "data" }));
-        //     // this script will be called by each presElement to get rendering-specific info that the PresBox knows about but which isn't written to the PresElement
-        //     // this is a design choice -- we could write this data to the presElements which would require a reaction to keep it up to date, and it would prevent
-        //     // the preselement docs from being part of multiple presentations since they would all have the same field, or we'd have to keep per-presentation data
-        //     // stored on each pres element.  
-        //     (this.searchItemTemplate as Doc).lookupField = ScriptField.MakeFunction("lookupSearchBoxField(container, field, data)",
-        //         { field: "string", data: Doc.name, container: Doc.name });
-        // }
     }
     @observable setupButtons = false;
     componentDidMount = () => {
-        if (this.setupButtons == false) {
+        if (this.setupButtons === false) {
 
-            runInAction(() => this.setupButtons == true);
+            runInAction(() => this.setupButtons = true);
         }
         if (this.inputRef.current) {
             this.inputRef.current.focus();
@@ -163,7 +116,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
 
 
     @action
-    getViews = (doc: Doc) => SearchUtil.GetViewsOfDocument(doc)
+    getViews = (doc: Doc) => SearchUtil.GetViewsOfDocument(doc);
 
 
     @observable newsearchstring: string = "";
@@ -203,9 +156,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
     enter = (e: React.KeyboardEvent) => {
         if (e.key === "Enter") {
             this.layoutDoc._searchString = this.newsearchstring;
-            // if (this._icons !== this._allIcons) {
-            //     runInAction(() => { this.expandedBucket = false });
-            // }
+
             if (StrCast(this.layoutDoc._searchString) !== "") {
                 console.log("OPEN");
                 runInAction(() => { this.open = true });
@@ -213,11 +164,8 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
             else {
                 console.log("CLOSE");
                 runInAction(() => { this.open = false });
-
             }
             this.submitSearch();
-
-
         }
     }
 
@@ -365,46 +313,58 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
                 this.props.Document.selectedDoc = selectedCollection.props.Document;
             }
             let docs = DocListCast(selectedCollection.dataDoc[Doc.LayoutFieldKey(selectedCollection.dataDoc)]);
-            let found: [Doc, string[], string[]][] = [];
-            let docsforFilter: Doc[] = []
+            const found: [Doc, string[], string[]][] = [];
+            const docsforFilter: Doc[] = []
             let newarray: Doc[] = [];
 
             while (docs.length > 0) {
                 newarray = [];
                 docs.forEach((d) => {
-                    if (d.data != undefined) {
+                    if (d.data !== undefined) {
                         let newdocs = DocListCast(d.data);
                         newdocs.forEach((newdoc) => {
                             newarray.push(newdoc);
 
                         });
                     }
-
-
-                    let hlights: string[] = [];
-
+                    const hlights: string[] = [];
                     const protos = Doc.GetAllPrototypes(d);
-                    let proto = protos[protos.length - 1];
                     protos.forEach(proto => {
                         Object.keys(proto).forEach(key => {
-                            // console.log(key, d[key]);
                             if (StrCast(d[key]).includes(query) && !hlights.includes(key)) {
                                 hlights.push(key);
                             }
-                        })
+                        });
                     });
                     if (hlights.length > 0) {
                         found.push([d, hlights, []]);
                         docsforFilter.push(d);
-                    };
+                    }
                 });
                 docs = newarray;
             }
             this._results = found;
             this.docsforfilter = docsforFilter;
             if (this.filter === true) {
-                console.log(docsforFilter);
                 selectedCollection.props.Document._searchDocs = new List<Doc>(docsforFilter);
+                docs = DocListCast(selectedCollection.dataDoc[Doc.LayoutFieldKey(selectedCollection.dataDoc)]);
+                while (docs.length > 0) {
+                    console.log("HIT");
+                    newarray = [];
+                    docs.forEach((d) => {
+                        if (d.data !== undefined) {
+                            console.log(d._searchDocs);
+                            d._searchDocs = new List<Doc>(docsforFilter);
+                            console.log(d);
+                            console.log(d._searchDocs);
+                            let newdocs = DocListCast(d.data);
+                            newdocs.forEach((newdoc) => {
+                                newarray.push(newdoc);
+                            });
+                        }
+                    });
+                    docs = newarray;
+                }
             }
             this._numTotalResults = found.length;
         }
@@ -468,7 +428,6 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
 
     @action
     submitSearch = async (reset?: boolean) => {
-        this.checkIcons();
         if (reset) {
             this.layoutDoc._searchString = "";
         }
@@ -644,13 +603,6 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
                 y += 300;
             }
         }
-        const filter: filterData = {
-            deletedDocsStatus: this._deletedDocsStatus,
-            authorFieldStatus: this._authorFieldStatus,
-            titleFieldStatus: this._titleFieldStatus,
-            basicWordStatus: this._basicWordStatus,
-            icons: this._icons,
-        }
         return Docs.Create.SearchDocument({ _autoHeight: true, _viewType: CollectionViewType.Schema, title: StrCast(this.layoutDoc._searchString), searchQuery: StrCast(this.layoutDoc._searchString) });
     }
 
@@ -693,7 +645,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
         const endIndex = 30;
         //this._endIndex = endIndex === -1 ? 12 : endIndex;
         this._endIndex = 30;
-        let headers = new Set<string>(["title", "author", "text", "lastModified"]);
+        const headers = new Set<string>(["title", "author", "lastModified", "text"]);
         if ((this._numTotalResults === 0 || this._results.length === 0) && this._openNoResults) {
             if (this.noresults === "") {
                 this.noresults = "No search results :(";
@@ -734,7 +686,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
                         if (i < this._results.length) result = this._results[i];
                         if (result) {
                             const highlights = Array.from([...Array.from(new Set(result[1]).values())]);
-                            let lines = new List<string>(result[2]);
+                            const lines = new List<string>(result[2]);
                             console.log(lines);
                             result[0].lines = lines;
                             result[0].highlighting = highlights.join(", ");
@@ -751,7 +703,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
                         result = this._results[i];
                         if (result) {
                             const highlights = Array.from([...Array.from(new Set(result[1]).values())]);
-                            let lines = new List<string>(result[2]);
+                            const lines = new List<string>(result[2]);
                             highlights.forEach((item) => headers.add(item));
                             console.log(lines);
                             result[0].lines = lines;
@@ -769,9 +721,9 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
                 }
             }
         }
-        let schemaheaders: SchemaHeaderField[] = [];
+        const schemaheaders: SchemaHeaderField[] = [];
         this.headerscale = headers.size;
-        headers.forEach((item) => schemaheaders.push(new SchemaHeaderField(item, "#f1efeb")))
+        headers.forEach((item) => schemaheaders.push(new SchemaHeaderField(item, "#f1efeb")));
         this.headercount = schemaheaders.length;
         this.props.Document._schemaHeaders = new List<SchemaHeaderField>(schemaheaders);
         if (this._maxSearchIndex >= this._numTotalResults) {
@@ -784,8 +736,8 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
     @observable headerscale: number = 0;
 
     findCommonElements(arr2: string[]) {
-        let arr1 = ["layout", "data"];
-        return arr1.some(item => arr2.includes(item))
+        const arr1 = ["layout", "data"];
+        return arr1.some(item => arr2.includes(item));
     }
 
     @computed
@@ -794,210 +746,10 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
     @computed
     get resultHeight() { return this._numTotalResults * 70; }
 
-    //if true, any keywords can be used. if false, all keywords are required.
-    @action.bound
-    handleWordQueryChange = async () => {
-        this._collectionStatus = !this._collectionStatus;
-        if (this._collectionStatus) {
-            let doc = await Cast(this.props.Document.keywords, Doc)
-            doc!.backgroundColor = "grey";
-
-        }
-        else {
-            let doc = await Cast(this.props.Document.keywords, Doc)
-            doc!.backgroundColor = "black";
-        }
-    }
-
-    @action.bound
-    handleNodeChange = async () => {
-        this._nodeStatus = !this._nodeStatus;
-
-        if (this._nodeStatus) {
-            this.expandSection(`node${this.props.Document[Id]}`);
-            let doc = await Cast(this.props.Document.nodes, Doc)
-            doc!.backgroundColor = "grey";
-
-        }
-        else {
-            this.collapseSection(`node${this.props.Document[Id]}`);
-            let doc = await Cast(this.props.Document.nodes, Doc)
-            doc!.backgroundColor = "black";
-        }
-    }
-
-    @action.bound
-    handleKeyChange = async () => {
-        this._keyStatus = !this._keyStatus;
-        if (this._keyStatus) {
-            this.expandSection(`key${this.props.Document[Id]}`);
-            let doc = await Cast(this.props.Document.keys, Doc)
-            doc!.backgroundColor = "grey";
-        }
-        else {
-            this.collapseSection(`key${this.props.Document[Id]}`);
-            let doc = await Cast(this.props.Document.keys, Doc)
-            doc!.backgroundColor = "black";
-        }
-    }
-
-    @action.bound
-    handleFilterChange = () => {
-        this._filterOpen = !this._filterOpen;
-        if (this._filterOpen) {
-            this.expandSection(`filterhead${this.props.Document[Id]}`);
-            document.getElementById(`filterhead${this.props.Document[Id]}`)!.style.padding = "5";
-            console.log(this.props.Document[Id])
-        }
-        else {
-            this.collapseSection(`filterhead${this.props.Document[Id]}`);
-
-
-        }
-    }
-
-    @computed
-    get menuHeight() {
-        return document.getElementById("hi")?.clientHeight;
-    }
-
-
-    collapseSection(thing: string) {
-        const id = this.props.Document[Id];
-        const element = document.getElementById(thing)!;
-        // get the height of the element's inner content, regardless of its actual size
-        const sectionHeight = element.scrollHeight;
-
-        // temporarily disable all css transitions
-        const elementTransition = element.style.transition;
-        element.style.transition = '';
-
-        // on the next frame (as soon as the previous style change has taken effect),
-        // explicitly set the element's height to its current pixel height, so we 
-        // aren't transitioning out of 'auto'
-        requestAnimationFrame(function () {
-            element.style.height = sectionHeight + 'px';
-            element.style.transition = elementTransition;
-
-            // on the next frame (as soon as the previous style change has taken effect),
-            // have the element transition to height: 0
-            requestAnimationFrame(function () {
-                element.style.height = 0 + 'px';
-                thing === `filterhead${id}` ? document.getElementById(`filterhead${id}`)!.style.padding = "0" : null;
-            });
-        });
-
-        // mark the section as "currently collapsed"
-        element.setAttribute('data-collapsed', 'true');
-    }
-
-    expandSection(thing: string) {
-        const element = document.getElementById(thing)!;
-        // get the height of the element's inner content, regardless of its actual size
-        const sectionHeight = element.scrollHeight;
-
-        // have the element transition to the height of its inner content
-        element.style.height = sectionHeight + 'px';
-
-        // when the next css transition finishes (which should be the one we just triggered)
-        element.addEventListener('transitionend', function handler(e) {
-            // remove this event listener so it only gets triggered once
-            element.removeEventListener('transitionend', handler);
-
-            // remove "height" from the element's inline styles, so it can return to its initial value
-            element.style.height = "auto";
-            //element.style.height = undefined;
-        });
-
-        // mark the section as "currently not collapsed"
-        element.setAttribute('data-collapsed', 'false');
-
-    }
-
-    autoset(thing: string) {
-        const element = document.getElementById(thing)!;
-        element.removeEventListener('transitionend', function (e) { });
-
-        // remove "height" from the element's inline styles, so it can return to its initial value
-        element.style.height = "auto";
-        //element.style.height = undefined;
-    }
-
-    @action.bound
-    updateTitleStatus = async () => {
-        this._titleFieldStatus = !this._titleFieldStatus;
-        if (this._titleFieldStatus) {
-            let doc = await Cast(this.props.Document.title, Doc)
-            doc!.backgroundColor = "grey";
-        }
-        else {
-            let doc = await Cast(this.props.Document.title, Doc)
-            doc!.backgroundColor = "black";
-        }
-    }
-
-    @action.bound
-    updateAuthorStatus = async () => {
-        this._authorFieldStatus = !this._authorFieldStatus;
-        if (this._authorFieldStatus) {
-            let doc = await Cast(this.props.Document.author, Doc)
-            doc!.backgroundColor = "grey";
-        }
-        else {
-            let doc = await Cast(this.props.Document.author, Doc)
-            doc!.backgroundColor = "black";
-        }
-    }
-
-    @action.bound
-    updateDeletedStatus = async () => {
-        this._deletedDocsStatus = !this._deletedDocsStatus;
-        if (this._deletedDocsStatus) {
-            let doc = await Cast(this.props.Document.deleted, Doc)
-            doc!.backgroundColor = "grey";
-        }
-        else {
-            let doc = await Cast(this.props.Document.deleted, Doc)
-            doc!.backgroundColor = "black";
-        }
-    }
-
     addButtonDoc = (doc: Doc) => Doc.AddDocToList(CurrentUserUtils.UserDocument.expandingButtons as Doc, "data", doc);
     remButtonDoc = (doc: Doc) => Doc.RemoveDocFromList(CurrentUserUtils.UserDocument.expandingButtons as Doc, "data", doc);
     moveButtonDoc = (doc: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean) => this.remButtonDoc(doc) && addDocument(doc);
 
-    @action.bound
-    updateIcon = async (icon: string) => {
-        if (this._icons.includes(icon)) {
-            _.pull(this._icons, icon);
-            let cap = icon.charAt(0).toUpperCase() + icon.slice(1)
-            console.log(cap);
-            let doc = await Cast(this.props.Document[cap], Doc)
-            doc!.backgroundColor = "black";
-        }
-        else {
-            this._icons.push(icon);
-            let cap = icon.charAt(0).toUpperCase() + icon.slice(1)
-            let doc = await Cast(this.props.Document[cap], Doc)
-            doc!.backgroundColor = "grey";
-        }
-    }
-
-    @action.bound
-    checkIcons = async () => {
-        for (let i = 0; i < this._allIcons.length; i++) {
-
-            let cap = this._allIcons[i].charAt(0).toUpperCase() + this._allIcons[i].slice(1)
-            let doc = await Cast(this.props.Document[cap], Doc)
-            if (this._icons.includes(this._allIcons[i])) {
-                doc!.backgroundColor = "grey";
-            }
-            else {
-                doc!.backgroundColor = "black";
-            }
-        }
-    }
-
     @computed get searchItemTemplate() { return Cast(Doc.UserDoc().searchItemTemplate, Doc, null); }
 
     getTransform = () => {
@@ -1016,16 +768,15 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
 
     @observable filter = false;
 
-
     //Make id layour document
     render() {
         this.props.Document._chromeStatus === "disabled";
         this.props.Document._searchDoc = true;
-        let cols = Cast(this.props.Document._schemaHeaders, listSpec(SchemaHeaderField), []).length;
+        const cols = Cast(this.props.Document._schemaHeaders, listSpec(SchemaHeaderField), []).length;
         let length = 0;
         cols > 5 ? length = 1076 : length = cols * 205 + 51;
         let height = 0;
-        let rows = this.children;
+        const rows = this.children;
         rows > 8 ? height = 31 + 31 * 8 : height = 31 * rows + 31;
         return (
             <div style={{ pointerEvents: "all" }} className="searchBox-container">
@@ -1045,10 +796,52 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
                                 this.filter = !this.filter && !this.scale;
                                 if (this.filter === true && this.currentSelectedCollection !== undefined) {
                                     this.currentSelectedCollection.props.Document._searchDocs = new List<Doc>(this.docsforfilter);
+                                    let newarray: Doc[] = [];
+                                    let docs: Doc[] = [];
+                                    docs = DocListCast(this.currentSelectedCollection.dataDoc[Doc.LayoutFieldKey(this.currentSelectedCollection.dataDoc)]);
+                                    while (docs.length > 0) {
+                                        console.log("HIT");
+                                        newarray = [];
+                                        docs.forEach((d) => {
+                                            if (d.data !== undefined) {
+                                                console.log(d._searchDocs);
+                                                d._searchDocs = new List<Doc>(this.docsforfilter);
+                                                console.log(d);
+                                                console.log(d._searchDocs);
+                                                let newdocs = DocListCast(d.data);
+                                                newdocs.forEach((newdoc) => {
+                                                    newarray.push(newdoc);
+                                                });
+                                            }
+                                        });
+                                        docs = newarray;
+                                    }
+
                                     this.currentSelectedCollection.props.Document._docFilters = new List<string>(Cast(this.props.Document._docFilters, listSpec("string"), []));
                                     this.props.Document.selectedDoc = this.currentSelectedCollection.props.Document;
                                 }
                                 else if (this.filter === false && this.currentSelectedCollection !== undefined) {
+                                    let newarray: Doc[] = [];
+                                    let docs: Doc[] = [];
+                                    docs = DocListCast(this.currentSelectedCollection.dataDoc[Doc.LayoutFieldKey(this.currentSelectedCollection.dataDoc)]);
+                                    while (docs.length > 0) {
+                                        console.log("HIT");
+                                        newarray = [];
+                                        docs.forEach((d) => {
+                                            if (d.data !== undefined) {
+                                                console.log(d._searchDocs);
+                                                d._searchDocs = new List<Doc>();
+                                                console.log(d);
+                                                console.log(d._searchDocs);
+                                                let newdocs = DocListCast(d.data);
+                                                newdocs.forEach((newdoc) => {
+                                                    newarray.push(newdoc);
+                                                });
+                                            }
+                                        });
+                                        docs = newarray;
+                                    }
+
                                     this.currentSelectedCollection.props.Document._searchDocs = new List<Doc>([]);
                                     this.currentSelectedCollection.props.Document._docFilters = undefined;
                                     this.props.Document.selectedDoc = undefined;
@@ -1075,12 +868,32 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
                                                     this.scale = !this.scale;
                                                     this.dataDoc[this.fieldKey] = new List<Doc>([]);
                                                     if (this.currentSelectedCollection !== undefined) {
+                                                        let newarray: Doc[] = [];
+                                                        let docs: Doc[] = [];
+                                                        docs = DocListCast(this.currentSelectedCollection.dataDoc[Doc.LayoutFieldKey(this.currentSelectedCollection.dataDoc)]);
+                                                        while (docs.length > 0) {
+                                                            console.log("HIT");
+                                                            newarray = [];
+                                                            docs.forEach((d) => {
+                                                                if (d.data !== undefined) {
+                                                                    console.log(d._searchDocs);
+                                                                    d._searchDocs = new List<Doc>();
+                                                                    console.log(d);
+                                                                    console.log(d._searchDocs);
+                                                                    let newdocs = DocListCast(d.data);
+                                                                    newdocs.forEach((newdoc) => {
+                                                                        newarray.push(newdoc);
+                                                                    });
+                                                                }
+                                                            });
+                                                            docs = newarray;
+                                                        }
                                                         this.currentSelectedCollection.props.Document._docFilters = undefined;
                                                         this.currentSelectedCollection.props.Document._searchDocs = undefined;
                                                         this.currentSelectedCollection = undefined;
                                                     }
                                                     this.submitSearch();
-                                                })
+                                                });
                                             }} />
                                         Collection
                                     </label>
@@ -1093,12 +906,32 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
                                                     this.dataDoc[this.fieldKey] = new List<Doc>([]);
                                                     this.filter = false;
                                                     if (this.currentSelectedCollection !== undefined) {
+                                                        let newarray: Doc[] = [];
+                                                        let docs: Doc[] = [];
+                                                        docs = DocListCast(this.currentSelectedCollection.dataDoc[Doc.LayoutFieldKey(this.currentSelectedCollection.dataDoc)]);
+                                                        while (docs.length > 0) {
+                                                            console.log("HIT");
+                                                            newarray = [];
+                                                            docs.forEach((d) => {
+                                                                if (d.data !== undefined) {
+                                                                    console.log(d._searchDocs);
+                                                                    d._searchDocs = new List<Doc>();
+                                                                    console.log(d);
+                                                                    console.log(d._searchDocs);
+                                                                    let newdocs = DocListCast(d.data);
+                                                                    newdocs.forEach((newdoc) => {
+                                                                        newarray.push(newdoc);
+                                                                    });
+                                                                }
+                                                            });
+                                                            docs = newarray;
+                                                        }
                                                         this.currentSelectedCollection.props.Document._docFilters = undefined;
                                                         this.currentSelectedCollection.props.Document._searchDocs = undefined;
                                                         this.currentSelectedCollection = undefined;
                                                     }
                                                     this.submitSearch();
-                                                })
+                                                });
                                             }} />
                                             DB
                                     </label>
@@ -1140,13 +973,3 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
         );
     }
 }
-
-Scripting.addGlobal(function lookupSearchBoxField(container: Doc, field: string, data: Doc) {
-    // if (field === 'indexInPres') return DocListCast(container[StrCast(container.presentationFieldKey)]).indexOf(data);
-    // if (field === 'presCollapsedHeight') return container._viewType === CollectionViewType.Schema ? 50 : 46;
-    // if (field === 'presStatus') return container.presStatus;
-    // if (field === '_itemIndex') return container._itemIndex;
-    if (field == "query") return container._searchString;
-    return undefined;
-});
-
diff --git a/src/client/views/search/SearchItem.scss b/src/client/views/search/SearchItem.scss
deleted file mode 100644
index 5ce022d41..000000000
--- a/src/client/views/search/SearchItem.scss
+++ /dev/null
@@ -1,186 +0,0 @@
-@import "../globalCssVariables";
-
-.searchItem-overview {
-    display: flex;
-    flex-direction: reverse;
-    justify-content: flex-end;
-    z-index: 0;
-}
-
-.searchBox-placeholder,
-.searchItem-overview .searchItem {
-    width: 100%;
-    background: $light-color-secondary;
-    padding: 8px;
-    min-height: 46px;
-    height:46px;
-    max-height: 150px;
-    height: auto;
-    z-index: 0;
-    display: flex;
-    overflow: visible;
-    box-shadow: rgb(156, 147, 150) 0.2vw 0.2vw 0.8vw;
-
-    .searchItem-body {
-        display: flex;
-        flex-direction: row;
-        width: 100%;
-
-        .searchItem-title-container {
-            width: 100%;
-            overflow: hidden;
-
-            .searchItem-title {
-                text-transform: uppercase;
-                text-align: left;
-                width: 100%;
-                font-weight: bold;
-            }
-        }
-
-        .searchItem-info {
-            display: flex;
-            justify-content: flex-end;
-
-            .icon-icons {
-                width: 50px
-            }
-
-            .icon-live {
-                width: 175px;
-                height: 0px;
-            }
-
-            .icon-icons {
-                height:auto;
-            }
-            .icon-icons,
-            .icon-live {
-                margin: auto;
-                overflow: visible;
-
-                .searchItem-type {
-                    display: inline-block;
-                    width: 100%;
-                    position: absolute;
-                    justify-content: center;
-                    align-items: center;
-                    position: relative;
-                    margin-right: 5px;
-                }
-
-                .pdfBox-cont {
-                    overflow: hidden;
-
-                    img {
-                        width: 100% !important;
-                        height: auto !important;
-                    }
-                }
-
-                .searchItem-type:hover+.searchItem-label {
-                    opacity: 1;
-                }
-
-                .searchItem-label {
-                    font-size: 10;
-                    position: relative;
-                    right: 0px;
-                    text-transform: capitalize;
-                    opacity: 0;
-                    -webkit-transition: opacity 0.2s ease-in-out;
-                    -moz-transition: opacity 0.2s ease-in-out;
-                    -o-transition: opacity 0.2s ease-in-out;
-                    transition: opacity 0.2s ease-in-out;
-                }
-            }
-
-            .icon-live:hover {
-                .pdfBox-cont {
-                    img {
-                        width: 100% !important;
-                    }
-                }
-            }
-        }
-
-        .searchItem-info:hover {
-            width: 60%;
-        }
-    }
-}
-
-.searchItem:hover~.searchBox-instances,
-.searchBox-instances:hover,
-.searchBox-instances:active {
-    opacity: 1;
-    background: $lighter-alt-accent;
-}
-
-.searchItem:hover {
-    transition: all 0.2s;
-    background: $lighter-alt-accent;
-}
-
-.searchItem-highlighting {
-    overflow: hidden;
-    text-overflow: ellipsis;
-    white-space: pre;
-}
-
-.searchBox-instances {
-    opacity: 1;
-    width:40px;
-    height:40px;
-    background: gray;
-    transition: all 0.2s ease;
-    color: black;
-    overflow: hidden;
-    right:-100;
-    display:inline-block;
-}
-
-
-.searchItem-overview:hover {
-    z-index: 1;
-}
-
-.searchBox-placeholder {
-    min-height: 46px;
-    margin-left: 150px;
-    width: calc(100% - 150px);
-    text-transform: uppercase;
-    text-align: left;
-    font-weight: bold;
-}
-
-.collection {
-    display: flex;
-}
-
-.collection-item {
-    width: 35px;
-}
-
-.bucket-title{
-    width:auto;
-    padding: 5px;
-    height: auto;
-    top: -18;
-    z-index: 55;
-    position: absolute;
-}
-
-.bucket-expand{
-    bottom: 0;
-    position: absolute;
-    width: 100%;
-    height: 15;
-    transform:none;
-    .bucket-expand:hover{
-        transform:none;
-    }
-    button:hover{
-        transform:none;
-    }
-}
\ No newline at end of file
diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx
deleted file mode 100644
index b61ed450f..000000000
--- a/src/client/views/search/SearchItem.tsx
+++ /dev/null
@@ -1,556 +0,0 @@
-import React = require("react");
-import { library } from '@fortawesome/fontawesome-svg-core';
-import { faCaretUp, faChartBar, faFile, faFilePdf, faFilm, faFingerprint, faGlobeAsia, faImage, faLink, faMusic, faObjectGroup, faStickyNote } from '@fortawesome/free-solid-svg-icons';
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { action, computed, observable, runInAction, IReactionDisposer, reaction } from "mobx";
-import { observer } from "mobx-react";
-import { Doc, DocCastAsync } from "../../../fields/Doc";
-import { Id } from "../../../fields/FieldSymbols";
-import { Cast, NumCast, StrCast } from "../../../fields/Types";
-import { emptyFunction, emptyPath, returnFalse, Utils, returnTrue, returnOne, returnZero, returnEmptyString, returnEmptyFilter } from "../../../Utils";
-import { DocumentType } from "../../documents/DocumentTypes";
-import { DocumentManager } from "../../util/DocumentManager";
-import { DragManager, SetupDrag } from "../../util/DragManager";
-import { SearchUtil } from "../../util/SearchUtil";
-import { Transform } from "../../util/Transform";
-import { SEARCH_THUMBNAIL_SIZE } from "../../views/globalCssVariables.scss";
-import { CollectionDockingView } from "../collections/CollectionDockingView";
-import { CollectionViewType, CollectionView } from "../collections/CollectionView";
-import { ParentDocSelector } from "../collections/ParentDocumentSelector";
-import { ContextMenu } from "../ContextMenu";
-import { ContentFittingDocumentView } from "../nodes/ContentFittingDocumentView";
-import { SearchBox } from "./SearchBox";
-import "./SearchItem.scss";
-import "./SelectorContextMenu.scss";
-import { FieldViewProps, FieldView } from "../nodes/FieldView";
-import { ViewBoxBaseComponent } from "../DocComponent";
-import { makeInterface, createSchema, listSpec } from "../../../fields/Schema";
-import { documentSchema } from "../../../fields/documentSchemas";
-import { PrefetchProxy } from "../../../fields/Proxy";
-import { Docs } from "../../documents/Documents";
-import { ScriptField } from "../../../fields/ScriptField";
-import { CollectionStackingView } from "../collections/CollectionStackingView";
-
-export interface SearchItemProps {
-    doc: Doc;
-    query: string;
-    highlighting: string[];
-    lines: string[];
-}
-
-library.add(faCaretUp);
-library.add(faObjectGroup);
-library.add(faStickyNote);
-library.add(faFile);
-library.add(faFilePdf);
-library.add(faFilm);
-library.add(faMusic);
-library.add(faLink);
-library.add(faChartBar);
-library.add(faGlobeAsia, faFingerprint);
-
-@observer
-export class SelectorContextMenu extends React.Component<SearchItemProps> {
-    @observable private _docs: { col: Doc, target: Doc }[] = [];
-    @observable private _otherDocs: { col: Doc, target: Doc }[] = [];
-
-    constructor(props: SearchItemProps) {
-        super(props);
-        this.fetchDocuments();
-    }
-
-    async fetchDocuments() {
-        const aliases = (await SearchUtil.GetViewsOfDocument(this.props.doc)).filter(doc => doc !== this.props.doc);
-        const { docs } = await SearchUtil.Search("", true, { fq: `data_l:"${this.props.doc[Id]}"` });
-        const map: Map<Doc, Doc> = new Map;
-        const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search("", true, { fq: `data_l:"${doc[Id]}"` }).then(result => result.docs)));
-        allDocs.forEach((docs, index) => docs.forEach(doc => map.set(doc, aliases[index])));
-        docs.forEach(doc => map.delete(doc));
-        runInAction(() => {
-            this._docs = docs.filter(doc => !Doc.AreProtosEqual(doc, CollectionDockingView.Instance.props.Document)).map(doc => ({ col: doc, target: this.props.doc }));
-            this._otherDocs = Array.from(map.entries()).filter(entry => !Doc.AreProtosEqual(entry[0], CollectionDockingView.Instance.props.Document)).map(([col, target]) => ({ col, target }));
-
-        });
-    }
-
-    getOnClick({ col, target }: { col: Doc, target: Doc }) {
-        return () => {
-            col = Doc.IsPrototype(col) ? Doc.MakeDelegate(col) : col;
-            if (col._viewType === CollectionViewType.Freeform) {
-                const newPanX = NumCast(target.x) + NumCast(target._width) / 2;
-                const newPanY = NumCast(target.y) + NumCast(target._height) / 2;
-                col._panX = newPanX;
-                col._panY = newPanY;
-            }
-            CollectionDockingView.AddRightSplit(col);
-        };
-    }
-    render() {
-        return (
-            <div className="parents">
-                <p className="contexts">Contexts:</p>
-                {[...this._docs, ...this._otherDocs].map(doc => {
-                    const item = React.createRef<HTMLDivElement>();
-                    return <div className="collection" key={doc.col[Id] + doc.target[Id]} ref={item}>
-                        <div className="collection-item" onPointerDown={
-                            SetupDrag(item, () => doc.col, undefined, undefined, () => SearchBox.Instance.closeSearch())}>
-                            <FontAwesomeIcon icon={faStickyNote} />
-                        </div>
-                        <a onClick={this.getOnClick(doc)}>{doc.col.title}</a>
-                    </div>;
-                })}
-            </div>
-        );
-    }
-}
-
-export interface LinkMenuProps {
-    doc1: Doc;
-    doc2: Doc;
-}
-
-@observer
-export class LinkContextMenu extends React.Component<LinkMenuProps> {
-
-    highlightDoc = (doc: Doc) => () => Doc.BrushDoc(doc);
-
-    unHighlightDoc = (doc: Doc) => () => Doc.UnBrushDoc(doc);
-
-    getOnClick = (col: Doc) => () => CollectionDockingView.AddRightSplit(col);
-
-    render() {
-        return (
-            <div className="parents">
-                <p className="contexts">Anchors:</p>
-                <div className="collection"><a onMouseEnter={this.highlightDoc(this.props.doc1)} onMouseLeave={this.unHighlightDoc(this.props.doc1)} onClick={this.getOnClick(this.props.doc1)}>Doc 1: {this.props.doc2.title}</a></div>
-                <div><a onMouseEnter={this.highlightDoc(this.props.doc2)} onMouseLeave={this.unHighlightDoc(this.props.doc2)} onClick={this.getOnClick(this.props.doc2)}>Doc 2: {this.props.doc1.title}</a></div>
-            </div>
-        );
-    }
-
-}
-
-
-type SearchSchema = makeInterface<[typeof documentSchema]>;
-
-export const SearchSchema = createSchema({
-    targetDoc: Doc,
-});
-
-const SearchDocument = makeInterface(documentSchema);
-
-
-
-@observer
-export class SearchItem extends ViewBoxBaseComponent<FieldViewProps, SearchSchema>(SearchDocument) {
-
-    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(SearchItem, fieldKey); }
-
-    constructor(props: any) {
-        super(props);
-        //this.rootDoc._viewType= CollectionViewType.Stacking;
-        this.props.Document._height = 46;
-        if (!this.searchItemTemplate) { // create exactly one presElmentBox template to use by any and all presentations.
-            Doc.UserDoc().searchItemTemplate = new PrefetchProxy(Docs.Create.SearchItemBoxDocument({ title: "search item template", backgroundColor: "transparent", _xMargin: 5, _height: 46, isTemplateDoc: true, isTemplateForField: "data" }));
-            // this script will be called by each presElement to get rendering-specific info that the PresBox knows about but which isn't written to the PresElement
-            // this is a design choice -- we could write this data to the presElements which would require a reaction to keep it up to date, and it would prevent
-            // the preselement docs from being part of multiple presentations since they would all have the same field, or we'd have to keep per-presentation data
-            // stored on each pres element.  
-            (this.searchItemTemplate as Doc).lookupField = ScriptField.MakeFunction("lookupSearchBoxField(container, field, data)",
-                { field: "string", data: Doc.name, container: Doc.name });
-        }
-
-    }
-
-    @observable _selected: boolean = false;
-
-    onClick = () => {
-        DocumentManager.Instance.jumpToDocument(this.rootDoc, false);
-    }
-    @observable _useIcons = true;
-    @observable _displayDim = 50;
-
-    @computed get query() { return StrCast(this.lookupField("query")); }
-
-    private _oldHeight: number = 46;
-
-    componentDidMount() {
-        let parent: Doc | undefined = undefined;
-        let height = 0;
-        if (this.rootDoc.parent) {
-            parent = Cast(this.rootDoc.parent, Doc, null);
-            if (parent !== undefined) {
-                height = (NumCast(parent._height));
-            }
-        }
-
-        this._reactionDisposer2 = reaction(
-            () => this._useIcons,
-            el => {
-                if (this.rootDoc.parent) {
-                    parent = Cast(this.rootDoc.parent, Doc, null) as Doc;
-                    height = (NumCast(parent._height));
-                };
-                console.log(height);
-                console.log(this._oldHeight);
-                setTimeout(() => {
-                    this._mainRef.current?.getBoundingClientRect() ? this.props.Document._height = this._mainRef.current?.getBoundingClientRect().height : null;
-                    parent !== undefined ? this._mainRef.current?.getBoundingClientRect() ? parent._height = -this._oldHeight + height + this._mainRef.current?.getBoundingClientRect().height : null : null;
-                    this._mainRef.current?.getBoundingClientRect() ? this._oldHeight = this._mainRef.current?.getBoundingClientRect().height : null;
-                    // this._oldHeight 55? this._oldHeight =55:null;
-                }, 1);
-            }
-        );
-
-        this._reactionDisposer3 = reaction(
-            () => this._displayLines,
-            el => {
-                if (this.rootDoc.parent) {
-                    parent = Cast(this.rootDoc.parent, Doc, null) as Doc;
-                    height = (NumCast(parent._height));
-                };
-                setTimeout(() => {
-                    this._mainRef.current?.getBoundingClientRect() ? this.props.Document._height = this._mainRef.current?.getBoundingClientRect().height : null;
-                    parent !== undefined ? this._mainRef.current?.getBoundingClientRect() ? parent._height = -this._oldHeight + height + this._mainRef.current?.getBoundingClientRect().height : null : null;
-                    this._mainRef.current?.getBoundingClientRect() ? this._oldHeight = this._mainRef.current?.getBoundingClientRect().height : null;
-                }, 1);
-            }
-        );
-
-        Doc.SetSearchQuery(this.query);
-        this.rootDoc.searchMatch = true;
-    }
-    componentWillUnmount() {
-        this.rootDoc.searchMatch = undefined;
-        this._reactionDisposer2 && this._reactionDisposer2();
-        this._reactionDisposer3 && this._reactionDisposer3();
-
-    }
-
-
-
-    private _reactionDisposer2?: IReactionDisposer;
-    private _reactionDisposer3?: IReactionDisposer;
-
-
-
-    @computed get highlightPos() { return NumCast(this.rootDoc.searchIndex) }
-
-    @action
-    public DocumentIcon() {
-        const layoutresult = StrCast(this.rootDoc.type);
-        if (!this._useIcons) {
-            const returnXDimension = () => this._useIcons ? 50 : Number(SEARCH_THUMBNAIL_SIZE);
-            const returnYDimension = () => this._displayDim;
-            const docview = <div
-                onPointerDown={action(() => {
-                    this._useIcons = !this._useIcons;
-                    this._displayDim = this._useIcons ? 50 : Number(SEARCH_THUMBNAIL_SIZE);
-                })}
-                onPointerEnter={action(() => this._displayDim = this._useIcons ? 50 : Number(SEARCH_THUMBNAIL_SIZE))} >
-                <ContentFittingDocumentView
-                    Document={this.rootDoc}
-                    LibraryPath={emptyPath}
-                    rootSelected={returnFalse}
-                    fitToBox={StrCast(this.rootDoc.type).indexOf(DocumentType.COL) !== -1}
-                    addDocument={returnFalse}
-                    removeDocument={returnFalse}
-                    addDocTab={returnFalse}
-                    pinToPres={returnFalse}
-                    docFilters={returnEmptyFilter}
-                    ContainingCollectionDoc={undefined}
-                    ContainingCollectionView={undefined}
-                    ScreenToLocalTransform={Transform.Identity}
-                    renderDepth={1}
-                    PanelWidth={returnXDimension}
-                    PanelHeight={returnYDimension}
-                    NativeWidth={returnZero}
-                    NativeHeight={returnZero}
-                    focus={emptyFunction}
-                    moveDocument={returnFalse}
-                    parentActive={returnFalse}
-                    whenActiveChanged={returnFalse}
-                    bringToFront={returnFalse}
-                    ContentScaling={returnOne}
-                />
-            </div>;
-            return docview;
-        }
-        const button = layoutresult.indexOf(DocumentType.PDF) !== -1 ? faFilePdf :
-            layoutresult.indexOf(DocumentType.IMG) !== -1 ? faImage :
-                layoutresult.indexOf(DocumentType.RTF) !== -1 ? faStickyNote :
-                    layoutresult.indexOf(DocumentType.VID) !== -1 ? faFilm :
-                        layoutresult.indexOf(DocumentType.COL) !== -1 ? faObjectGroup :
-                            layoutresult.indexOf(DocumentType.AUDIO) !== -1 ? faMusic :
-                                layoutresult.indexOf(DocumentType.LINK) !== -1 ? faLink :
-                                    layoutresult.indexOf(DocumentType.WEB) !== -1 ? faGlobeAsia :
-                                        faCaretUp;
-        return <div><div onClick={action(() => { this._useIcons = false; this._displayDim = Number(SEARCH_THUMBNAIL_SIZE); })} >
-            <FontAwesomeIcon icon={button} size="2x" />
-        </div>
-            <div className="searchItem-label">{this.rootDoc.type ? this.rootDoc.type : "Other"}</div>
-        </div>
-            ;
-    }
-
-    collectionRef = React.createRef<HTMLDivElement>();
-
-    @action
-    pointerDown = (e: React.PointerEvent) => { e.preventDefault(); e.button === 0 && SearchBox.Instance.openSearch(e); }
-
-    @action
-    nextHighlight = (e: React.MouseEvent) => {
-        e.preventDefault();
-        e.stopPropagation();
-        //e.button === 0 && SearchBox.Instance.openSearch(e);
-
-        this.rootDoc!.searchMatch = false;
-        setTimeout(() => this.rootDoc!.searchMatch = true, 0);
-        this.rootDoc.searchIndex = NumCast(this.rootDoc.searchIndex);
-        this.length = NumCast(this.rootDoc!.length);
-    }
-
-    @action
-    nextHighlight2 = (e: React.MouseEvent) => {
-        e.preventDefault();
-        e.stopPropagation();
-
-        //e.button === 0 && SearchBox.Instance.openSearch(e);
-
-        this.rootDoc!.searchMatch2 = false;
-        setTimeout(() => this.rootDoc!.searchMatch2 = true, 0);
-        this.rootDoc.searchIndex = NumCast(this.rootDoc.searchIndex);
-
-        this.length = NumCast(this.rootDoc!.length);
-    }
-
-    @observable length: number | undefined = 0;
-
-    highlightDoc = (e: React.PointerEvent) => {
-        if (this.rootDoc!.type === DocumentType.LINK) {
-            if (this.rootDoc!.anchor1 && this.rootDoc!.anchor2) {
-
-                const doc1 = Cast(this.rootDoc!.anchor1, Doc, null);
-                const doc2 = Cast(this.rootDoc!.anchor2, Doc, null);
-                Doc.BrushDoc(doc1);
-                Doc.BrushDoc(doc2);
-            }
-        } else {
-            Doc.BrushDoc(this.rootDoc!);
-        }
-        e.stopPropagation();
-    }
-
-    unHighlightDoc = (e: React.PointerEvent) => {
-        if (this.rootDoc!.type === DocumentType.LINK) {
-            if (this.rootDoc!.anchor1 && this.rootDoc!.anchor2) {
-
-                const doc1 = Cast(this.rootDoc!.anchor1, Doc, null);
-                const doc2 = Cast(this.rootDoc!.anchor2, Doc, null);
-                Doc.UnBrushDoc(doc1);
-                Doc.UnBrushDoc(doc2);
-            }
-        } else {
-            Doc.UnBrushDoc(this.rootDoc!);
-        }
-    }
-
-    onContextMenu = (e: React.MouseEvent) => {
-        e.preventDefault();
-        e.stopPropagation();
-        ContextMenu.Instance.clearItems();
-        ContextMenu.Instance.addItem({
-            description: "Copy ID", event: () => {
-                Utils.CopyText(StrCast(this.rootDoc[Id]));
-            },
-            icon: "fingerprint"
-        });
-        ContextMenu.Instance.displayMenu(e.clientX, e.clientY);
-    }
-
-    _downX = 0;
-    _downY = 0;
-    _target: any;
-    onPointerDown = (e: React.PointerEvent<HTMLDivElement>) => {
-        this._downX = e.clientX;
-        this._downY = e.clientY;
-        e.stopPropagation();
-        this._target = e.currentTarget;
-        document.removeEventListener("pointermove", this.onPointerMoved);
-        document.removeEventListener("pointerup", this.onPointerUp);
-        document.addEventListener("pointermove", this.onPointerMoved);
-        document.addEventListener("pointerup", this.onPointerUp);
-    }
-    onPointerMoved = (e: PointerEvent) => {
-        if (Math.abs(e.clientX - this._downX) > Utils.DRAG_THRESHOLD ||
-            Math.abs(e.clientY - this._downY) > Utils.DRAG_THRESHOLD) {
-            document.removeEventListener("pointermove", this.onPointerMoved);
-            document.removeEventListener("pointerup", this.onPointerUp);
-            const doc = Doc.IsPrototype(this.rootDoc) ? Doc.MakeDelegate(this.rootDoc) : this.rootDoc;
-            DragManager.StartDocumentDrag([this._target], new DragManager.DocumentDragData([doc]), e.clientX, e.clientY);
-        }
-    }
-    onPointerUp = (e: PointerEvent) => {
-        document.removeEventListener("pointermove", this.onPointerMoved);
-        document.removeEventListener("pointerup", this.onPointerUp);
-    }
-
-    @computed
-    get contextButton() {
-        return <ParentDocSelector Document={this.rootDoc} addDocTab={(doc, where) => CollectionDockingView.AddRightSplit(doc)} />;
-    }
-
-    @computed get searchElementDoc() { return this.rootDoc; }
-    // @computed get targetDoc() { return this.searchElementDoc?.targetDoc as Doc; }
-
-    @computed get searchItemTemplate() { return Cast(Doc.UserDoc().searchItemTemplate, Doc, null); }
-    childLayoutTemplate = () => this.layoutDoc._viewType === CollectionViewType.Stacking ? this.searchItemTemplate : undefined;
-    getTransform = () => {
-        return this.props.ScreenToLocalTransform().translate(-5, -65);// listBox padding-left and pres-box-cont minHeight
-    }
-    panelHeight = () => {
-        return this.props.PanelHeight();
-    }
-    selectElement = (doc: Doc) => {
-        //this.gotoDocument(this.childDocs.indexOf(doc), NumCast(this.layoutDoc._itemIndex));
-    }
-
-    newsearch() {
-        runInAction(() => {
-            if (StrCast(this.rootDoc.bucketfield) !== "results") {
-                SearchBox.Instance._icons = [StrCast(this.rootDoc.bucketfield)];
-                SearchBox.Instance._icons = SearchBox.Instance._icons;
-            }
-            else {
-                SearchBox.Instance._icons = SearchBox.Instance._allIcons;
-            }
-            SearchBox.Instance.submitSearch();
-        })
-    }
-
-    @action
-    returnLines() {
-        if ((Cast(this.rootDoc.lines, listSpec("string")))!.length > 1) {
-            if (!this._displayLines) {
-                console.log(Cast(this.rootDoc.lines, listSpec("string")));
-                return <div style={{ width: 10 }}
-                    onPointerDown={action(() => {
-                        this._displayLines = !this._displayLines;
-                        //this._displayDim = this._useIcons ? 50 : Number(SEARCH_THUMBNAIL_SIZE);
-                    })}
-                //onPointerEnter={action(() => this._displayDim = this._useIcons ? 50 : Number(SEARCH_THUMBNAIL_SIZE))}
-                >
-                    {Cast(this.rootDoc.lines, listSpec("string"))!.filter((m, i) => i).map((l, i) => <div style={{ overflow: "visible" }} id={i.toString()} className="searchItem-highlighting">{l}</div>)}
-                </div>;;
-            }
-        }
-    }
-
-    //this._displayDim = Number(SEARCH_THUMBNAIL_SIZE); 
-
-    @observable _displayLines: boolean = true;
-
-    returnButtons() {
-        return <div>
-            <div onClick={action(() => {
-                this.rootDoc!.type === DocumentType.PDF ? this._displayLines = !this._displayLines : null;
-            })}>
-                {this.rootDoc!.type === DocumentType.PDF ? "Expand Lines" : null}
-                {NumCast(this.rootDoc!.length) > 1 ? `Instance ${NumCast(this.rootDoc.searchIndex) === 0 ? NumCast(this.rootDoc.length) : NumCast(this.rootDoc.searchIndex)} of ${NumCast(this.rootDoc.length)}` : null}
-                <button onClick={this.nextHighlight} style={{ padding: 2, position: "absolute", left: 77 }}>
-                    <FontAwesomeIcon icon="arrow-up" size="sm" />
-                </button>
-                <button onClick={this.nextHighlight2} style={{ padding: 2, position: "absolute", left: 87 }}>
-                    <FontAwesomeIcon icon="arrow-down" size="sm" />
-                </button>
-            </div>
-            <div>
-                <div style={{ background: "lightgrey" }}>
-                    {this.returnLines()}
-                </div>
-            </div>
-        </div>
-    }
-
-    private _mainRef: React.RefObject<HTMLDivElement> = React.createRef();
-
-
-    render() {
-        const doc1 = Cast(this.rootDoc!.anchor1, Doc);
-        const doc2 = Cast(this.rootDoc!.anchor2, Doc);
-        if (StrCast(this.rootDoc.bucketfield) === "webs") {
-            this.props.Document._viewType = CollectionViewType.Stacking;
-            this.props.Document._chromeStatus = 'disabled';
-            this.props.Document._height = this.rootDoc._height;
-            return <div>
-                <CollectionView {...this.props}
-                    Document={this.props.Document}
-                    PanelHeight={this.panelHeight}
-                    whenActiveChanged={emptyFunction}
-                    onClick={undefined}
-                    moveDocument={returnFalse}
-                    childLayoutTemplate={undefined}
-                    addDocument={undefined}
-                    removeDocument={returnFalse}
-                    focus={this.selectElement}
-                    ScreenToLocalTransform={this.getTransform} />
-            </div>
-        }
-        if (this.rootDoc.isBucket === true) {
-            this.props.Document._viewType = CollectionViewType.Stacking;
-            this.props.Document._chromeStatus = 'disabled';
-            this.props.Document._height = this.rootDoc._height;
-
-            return <div>
-                <CollectionView {...this.props}
-                    Document={this.props.Document}
-                    PanelHeight={this.panelHeight}
-                    whenActiveChanged={emptyFunction}
-                    onClick={undefined}
-                    moveDocument={returnFalse}
-                    childLayoutTemplate={this.childLayoutTemplate}
-                    addDocument={undefined}
-                    removeDocument={returnFalse}
-                    focus={this.selectElement}
-                    ScreenToLocalTransform={this.getTransform} />
-                <button onClick={() => this.newsearch()} className="bucket-expand" style={{ transform: "none", fontSize: "100%", textTransform: "none", background: "lightgray", color: "black", bottom: 8, marginBottom: -2, paddingTop: 2, fontFamily: "Arial, sans-serif" }}>See all {StrCast(this.rootDoc.bucketfield)}...
-            </button>
-            </div>
-        }
-        else if (this.rootDoc.isBucket === false) {
-            this.props.Document._chromeStatus = 'disabled';
-            return <div className="searchItem">
-                <div className="searchItem-body" >
-                    <div className="searchItem-title-container">
-                        <div className="searchItem-title" style={{ height: "10px", overflow: "hidden", textOverflow: "ellipsis" }}>No Search Results</div>
-                    </div>
-                </div>
-            </div>
-        }
-        else {
-            return <div className="searchItem-overview" onPointerDown={this.pointerDown} onContextMenu={this.onContextMenu}>
-                <div ref={this._mainRef} className="searchItem" onPointerEnter={this.highlightDoc} onPointerLeave={this.unHighlightDoc}>
-                    <div className="searchItem-body" onClick={this.onClick}>
-                        <div className="searchItem-title-container">
-                            <div className="searchItem-title" style={{ height: "10px", overflow: "hidden", textOverflow: "ellipsis" }}>{StrCast(this.rootDoc.title)}</div>
-                            <div className="searchItem-highlighting">
-                                {this.rootDoc.highlighting ? StrCast(this.rootDoc.highlighting).length ? "Matched fields:" + StrCast(this.rootDoc.highlighting) : Cast(this.rootDoc.lines, listSpec("string"))!.length ? Cast(this.rootDoc.lines, listSpec("string"))![0] : "" : null}</div>
-                            <div className={`icon-${this._displayLines ? "q" : "a"}`}>
-                                {NumCast(this.rootDoc.length) > 1 || this.rootDoc!.type === DocumentType.PDF ? this.returnButtons() : null}
-                            </div>
-                        </div>
-                    </div>
-                    <div className="searchItem-info" style={{ width: this._useIcons ? "30px" : "100%" }}>
-                        <div className={`icon-${this._useIcons ? "icons" : "live"}`}>
-                            <div className="searchItem-type" title="Click to Preview" onPointerDown={this.onPointerDown}>{this.DocumentIcon()}</div>
-                        </div>
-                    </div>
-                    {/* <div className="searchItem-context" title="Drag as document">
-                    {(doc1 instanceof Doc && doc2 instanceof Doc) && this.rootDoc!.type === DocumentType.LINK ? <LinkContextMenu doc1={doc1} doc2={doc2} /> :
-                        this.contextButton}
-                </div> */}
-                </div>
-            </div>;
-        }
-    }
-} 
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From c78fdc76a7aec8ed37e8a97c9ddafbf88d5a0392 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Tue, 4 Aug 2020 23:12:04 -0500
Subject: ink flyouts for colors

---
 .../collectionFreeForm/PropertiesView.tsx          | 31 +++++++++++++---------
 1 file changed, 19 insertions(+), 12 deletions(-)

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

diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index e2e026ca2..a6b1849b1 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -27,6 +27,9 @@ import { ColorState, SketchPicker } from "react-color";
 import AntimodeMenu from "../../AntimodeMenu";
 import "./FormatShapePane.scss";
 import { discovery_v1 } from "googleapis";
+const higflyout = require("@hig/flyout");
+export const { anchorPoints } = higflyout;
+export const Flyout = higflyout.default;
 
 
 interface PropertiesViewProps {
@@ -582,14 +585,18 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     set colorFil(value) { value && (this._lastFill = value); this.selectedDoc && (this.selectedDoc.fillColor = value ? value : undefined); }
     set colorStk(value) { value && (this._lastLine = value); this.selectedDoc && (this.selectedDoc.color = value ? value : undefined); }
 
-    colorButton(value: string, setter: () => {}) {
-        return <div className="color-button" key="color" onPointerDown={undoBatch(action(e => setter()))}>
-            <div className="color-button-preview" style={{
-                backgroundColor: value ?? "121212", width: 15, height: 15,
-                display: value === "" || value === "transparent" ? "none" : ""
-            }} />
-            {value === "" || value === "transparent" ? <p style={{ fontSize: 25, color: "red", marginTop: -14, position: "fixed" }}>☒</p> : ""}
-        </div>;
+    colorButton(value: string, type: string, setter: () => {}) {
+        return <Flyout anchorPoint={anchorPoints.LEFT_TOP}
+            content={type === "fill" ? this.fillPicker : this.linePicker}>
+            <div className="color-button" key="color" onPointerDown={undoBatch(action(e => setter()))}>
+                <div className="color-button-preview" style={{
+                    backgroundColor: value ?? "121212", width: 15, height: 15,
+                    display: value === "" || value === "transparent" ? "none" : ""
+                }} />
+                {value === "" || value === "transparent" ? <p style={{ fontSize: 25, color: "red", marginTop: -14, position: "fixed" }}>☒</p> : ""}
+            </div>
+        </Flyout>;
+
     }
 
     @undoBatch
@@ -615,8 +622,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
             color={type === "stk" ? this.colorStk : this.colorFil} />;
     }
 
-    @computed get fillButton() { return this.colorButton(this.colorFil, () => { this._fillBtn = !this._fillBtn; this._lineBtn = false; return true; }); }
-    @computed get lineButton() { return this.colorButton(this.colorStk, () => { this._lineBtn = !this._lineBtn; this._fillBtn = false; return true; }); }
+    @computed get fillButton() { return this.colorButton(this.colorFil, "fill", () => { this._fillBtn = !this._fillBtn; this._lineBtn = false; return true; }); }
+    @computed get lineButton() { return this.colorButton(this.colorStk, "line", () => { this._lineBtn = !this._lineBtn; this._fillBtn = false; return true; }); }
 
     @computed get fillPicker() { return this.colorPicker((color: string) => this.colorFil = color, "fil"); }
     @computed get linePicker() { return this.colorPicker((color: string) => this.colorStk = color, "stk"); }
@@ -633,8 +640,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                     <div className="stroke-button">{this.lineButton}</div>
                 </div>
             </div>
-            {this._fillBtn ? this.fillPicker : ""}
-            {this._lineBtn ? this.linePicker : ""}
+            {/* {this._fillBtn ? this.fillPicker : ""}
+            {this._lineBtn ? this.linePicker : ""} */}
         </div>;
     }
 
-- 
cgit v1.2.3-70-g09d2


From 2b8fd3bbc922fdb9b82ed5cabe6308b37077fb9e Mon Sep 17 00:00:00 2001
From: usodhi <61431818+usodhi@users.noreply.github.com>
Date: Wed, 5 Aug 2020 13:23:47 +0530
Subject: comments and minor changes

---
 src/client/util/CurrentUserUtils.ts                   |  2 +-
 src/client/views/MainView.tsx                         |  2 +-
 .../collections/collectionFreeForm/PropertiesView.tsx | 19 +++++++++++++++++++
 src/client/views/nodes/DocumentView.tsx               |  4 ++--
 4 files changed, 23 insertions(+), 4 deletions(-)

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

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 8023df8b4..aceab9dd2 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -824,7 +824,7 @@ export class CurrentUserUtils {
     // Right sidebar is where mobile uploads are contained
     static setupRightSidebar(doc: Doc) {
         if (doc["sidebar-sharing"] === undefined) {
-            doc["sidebar-sharing"] = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "Mobile Uploads" }));
+            doc["sidebar-sharing"] = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "Shared Documents", childDropAction: "alias" }));
         }
     }
 
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 66545ea1f..61520bc36 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -408,7 +408,7 @@ export class MainView extends React.Component {
     }
     sidebarScreenToLocal = () => new Transform(0, (CollectionMenu.Instance.Pinned ? -35 : 0), 1);
     //sidebarScreenToLocal = () => new Transform(0, (RichTextMenu.Instance.Pinned ? -35 : 0) + (CollectionMenu.Instance.Pinned ? -35 : 0), 1);
-    mainContainerXf = () => this.sidebarScreenToLocal().translate(0, -this._buttonBarHeight);
+    mainContainerXf = () => this.sidebarScreenToLocal().translate(-55, 0);
 
     @computed get closePosition() { return 55 + this.flyoutWidth; }
     @computed get flyout() {
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index f5e0cd077..31962837c 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -266,11 +266,17 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         }
     }
 
+    /**
+     * Handles the changing of a user's permissions from the permissions panel.
+     */
     @undoBatch
     changePermissions = (e: any, user: string) => {
         SharingManager.Instance.shareFromPropertiesSidebar(user, e.currentTarget.value as SharingPermissions, this.selectedDoc!);
     }
 
+    /**
+     * @returns the options for the permissions dropdown.
+     */
     getPermissionsSelect(user: string) {
         return <select className="permissions-select"
             onChange={e => this.changePermissions(e, user)}>
@@ -283,6 +289,9 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         </select>;
     }
 
+    /**
+     * @returns the notification icon. On clicking, it should notify someone of a document been shared with them.
+     */
     @computed get notifyIcon() {
         return <Tooltip title={<><div className="dash-tooltip">Notify with message</div></>}>
             <div className="notify-button">
@@ -291,6 +300,9 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         </Tooltip>;
     }
 
+    /**
+     * ... next to the owner that opens the main SharingManager interface on click.
+     */
     @computed get expansionIcon() {
         return <Tooltip title={<><div className="dash-tooltip">{"Show more permissions"}</div></>}>
             <div className="expansion-button" onPointerDown={() => {
@@ -303,6 +315,9 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         </Tooltip>;
     }
 
+    /**
+     * @returns a row of the permissions panel
+     */
     sharingItem(name: string, effectiveAcl: symbol, permission?: string) {
         return <div className="propertiesView-sharingTable-item">
             <div className="propertiesView-sharingTable-item-name" style={{ width: name !== "Me" ? "85px" : "80px" }}> {name} </div>
@@ -314,6 +329,9 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         </div>;
     }
 
+    /**
+     * @returns the sharing and permissiosn panel.
+     */
     @computed get sharingTable() {
         const AclMap = new Map<symbol, string>([
             [AclPrivate, SharingPermissions.None],
@@ -333,6 +351,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
             }
         }
 
+        // shifts the current user and the owner to the top of the doc.
         tableEntries.unshift(this.sharingItem("Me", effectiveAcl, Doc.CurrentUserEmail === this.selectedDoc!.author ? "Owner" : StrCast(this.selectedDoc![`ACL-${Doc.CurrentUserEmail.replace(".", "_")}`])));
         if (Doc.CurrentUserEmail !== this.selectedDoc!.author) tableEntries.unshift(this.sharingItem(StrCast(this.selectedDoc!.author), effectiveAcl, "Owner"));
 
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 81738f234..60075d5cf 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -179,7 +179,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         RadialMenu.Instance.openMenu(pt.pageX - 15, pt.pageY - 15);
 
         // RadialMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "onRight"), icon: "map-pin", selected: -1 });
-        RadialMenu.Instance.addItem({ description: "Delete", event: () => { this.props.ContainingCollectionView?.removeDocument(this.props.Document), RadialMenu.Instance.closeMenu(); }, icon: "external-link-square-alt", selected: -1 });
+        const effectiveAcl = GetEffectiveAcl(this.props.Document);
+        (effectiveAcl === AclEdit || effectiveAcl === AclAdmin) && RadialMenu.Instance.addItem({ description: "Delete", event: () => { this.props.ContainingCollectionView?.removeDocument(this.props.Document), RadialMenu.Instance.closeMenu(); }, icon: "external-link-square-alt", selected: -1 });
         // RadialMenu.Instance.addItem({ description: "Open in a new tab", event: () => this.props.addDocTab(this.props.Document, "onRight"), icon: "trash", selected: -1 });
         RadialMenu.Instance.addItem({ description: "Pin", event: () => this.props.pinToPres(this.props.Document), icon: "map-pin", selected: -1 });
         RadialMenu.Instance.addItem({ description: "Open", event: () => MobileInterface.Instance.handleClick(this.props.Document), icon: "trash", selected: -1 });
@@ -762,7 +763,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "fingerprint" });
             Doc.AreProtosEqual(this.props.Document, Doc.UserDoc()) && moreItems.push({ description: "Toggle Always Show Link End", event: () => Doc.UserDoc()["documentLinksButton-hideEnd"] = !Doc.UserDoc()["documentLinksButton-hideEnd"], icon: "eye" });
         }
-        //GetEffectiveAcl(this.props.Document) === AclEdit && moreItems.push({ description: "Delete", event: this.deleteClicked, icon: "trash" });
 
         const effectiveAcl = GetEffectiveAcl(this.props.Document);
         (effectiveAcl === AclEdit || effectiveAcl === AclAdmin) && moreItems.push({ description: "Delete", event: this.deleteClicked, icon: "trash" });
-- 
cgit v1.2.3-70-g09d2


From 7e18d27de76bd2b58281841910aee3c4829269dd Mon Sep 17 00:00:00 2001
From: yunahi <60233430+yunahi@users.noreply.github.com>
Date: Thu, 6 Aug 2020 00:21:23 +0900
Subject: fixed bugs after testing

---
 src/client/views/DocumentDecorations.scss          |  3 +-
 src/client/views/DocumentDecorations.tsx           | 38 ++++++++++++++++---
 src/client/views/GestureOverlay.tsx                | 40 +++++++++++++++++++-
 src/client/views/InkingStroke.tsx                  | 30 +++++++++------
 src/client/views/collections/CollectionMenu.tsx    |  6 ++-
 .../collectionFreeForm/FormatShapePane.tsx         |  2 +
 .../collectionFreeForm/PropertiesView.tsx          | 43 ++++++++++++----------
 7 files changed, 121 insertions(+), 41 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss
index 424a06431..5401623e8 100644
--- a/src/client/views/DocumentDecorations.scss
+++ b/src/client/views/DocumentDecorations.scss
@@ -24,8 +24,7 @@ $linkGap : 3px;
 
     .documentDecorations-rotation {
         pointer-events: auto;
-        // cursor: grabbing;
-        cursor: ns-resize;
+        cursor: alias;
         width: 10px;
         height: 10px;
     }
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index f16cb273b..1ae7d6617 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -27,6 +27,8 @@ import { GetEffectiveAcl } from '../../fields/util';
 import { DocumentIcon } from './nodes/DocumentIcon';
 import { render } from 'react-dom';
 import { createLessThan } from 'typescript';
+import FormatShapePane from './collections/collectionFreeForm/FormatShapePane';
+import { PropertiesView } from './collections/collectionFreeForm/PropertiesView';
 
 library.add(faCaretUp);
 library.add(faObjectGroup);
@@ -59,12 +61,15 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     private _linkBoxHeight = 20 + 3; // link button height + margin
     private _titleHeight = 20;
     private _resizeUndo?: UndoManager.Batch;
+    private _rotateUndo?: UndoManager.Batch;
     private _offX = 0; _offY = 0;  // offset from click pt to inner edge of resize border
     private _snapX = 0; _snapY = 0; // last snapped location of resize border
     private _prevX = 0;
     private _prevY = 0;
     private _centerPoints: { X: number, Y: number }[] = [];
     private _inkDocs: { x: number, y: number, width: number, height: number }[] = [];
+    private _natWid = 0;
+    private _natHei = 0;
 
     @observable private _accumulatedTitle = "";
     @observable private _titleControlString: string = "#title";
@@ -258,8 +263,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         return false;
     }
 
+    @undoBatch
     @action
     onRotateDown = (e: React.PointerEvent): void => {
+        this._rotateUndo = UndoManager.StartBatch("rotatedown");
+
         setupMoveUpEvents(this, e, this.onRotateMove, this.onRotateUp, (e) => { });
         this._prevX = e.clientX;
         this._prevY = e.clientY;
@@ -281,6 +289,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         }));
 
     }
+
+    @undoBatch
     @action
     onRotateMove = (e: PointerEvent, down: number[]): boolean => {
 
@@ -332,12 +342,15 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
 
     onRotateUp = (e: PointerEvent) => {
         this._centerPoints = [];
+        this._rotateUndo?.end();
+        this._rotateUndo = undefined;
     }
 
 
 
     _initialAutoHeight = false;
     _dragHeights = new Map<Doc, number>();
+
     @action
     onPointerDown = (e: React.PointerEvent): void => {
 
@@ -346,8 +359,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             const doc = Document(element.rootDoc);
             if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height) {
                 this._inkDocs.push({ x: doc.x, y: doc.y, width: doc._width, height: doc._height });
+                if (FormatShapePane.Instance._lock) {
+                    doc._nativeHeight = doc._height;
+                    doc._nativeWidth = doc._width;
+                }
             }
-
         }));
 
         setupMoveUpEvents(this, e, this.onPointerMove, this.onPointerUp, (e) => { });
@@ -373,7 +389,15 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
     onPointerMove = (e: PointerEvent, down: number[], move: number[]): boolean => {
         const first = SelectionManager.SelectedDocuments()[0];
         let thisPt = { thisX: e.clientX - this._offX, thisY: e.clientY - this._offY };
-        const fixedAspect = first.layoutDoc._nativeWidth ? NumCast(first.layoutDoc._nativeWidth) / NumCast(first.layoutDoc._nativeHeight) : 0;
+        var fixedAspect = first.layoutDoc._nativeWidth ? NumCast(first.layoutDoc._nativeWidth) / NumCast(first.layoutDoc._nativeHeight) : 0;
+        SelectionManager.SelectedDocuments().forEach(action((element: DocumentView) => {
+            const doc = Document(element.rootDoc);
+            if (doc.type === DocumentType.INK && doc._width && doc._height && FormatShapePane.Instance._lock) {
+                fixedAspect = NumCast(doc._nativeWidth) / NumCast(doc._nativeHeight);
+            }
+        }));
+
+
         if (fixedAspect && (this._resizeHdlId === "documentDecorations-bottomRightResizer" || this._resizeHdlId === "documentDecorations-topLeftResizer")) { // need to generalize for bl and tr drag handles
             const project = (p: number[], a: number[], b: number[]) => {
                 const atob = [b[0] - a[0], b[1] - a[1]];
@@ -544,7 +568,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                     doc.data = new InkField(newPoints);
 
                 }
-
+                doc._nativeWidth = 0;
+                doc._nativeHeight = 0;
             }
         }));
     }
@@ -639,10 +664,14 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             bounds.y = bounds.b - (this._resizeBorderWidth + this._linkBoxHeight + this._titleHeight);
         }
         var offset = 0;
+        var rotButton = <></>;
         //make offset larger for ink to edit points
         if (seldoc.rootDoc.type === DocumentType.INK) {
             offset = 20;
+            rotButton = <div id="documentDecorations-rotation" title="rotate" className="documentDecorations-rotation"
+                onPointerDown={this.onRotateDown}> ⟲ </div>;
         }
+
         return (<div className="documentDecorations" style={{ background: darkScheme }} >
             <div className="documentDecorations-background" style={{
                 width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px",
@@ -670,8 +699,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
                     <Tooltip title={<><div className="dash-tooltip">Open Document In Tab</div></>} placement="top"><div className="documentDecorations-openInTab" onPointerDown={this.onMaximizeDown}>
                         {SelectionManager.SelectedDocuments().length === 1 ? <FontAwesomeIcon icon="external-link-alt" className="documentView-minimizedIcon" /> : "..."}
                     </div></Tooltip>
-                    <div id="documentDecorations-rotation" className="documentDecorations-rotation"
-                        onPointerDown={this.onRotateDown}> ⟲ </div>
+                    {rotButton}
                     <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer"
                         onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                     <div id="documentDecorations-topResizer" className="documentDecorations-resizer"
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 7c0a8635e..30df7cf9a 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -676,6 +676,15 @@ export default class GestureOverlay extends Touchable {
         var left = Math.min(...xs);
         var bottom = Math.max(...ys);
         var top = Math.min(...ys);
+        const firstx = this._points[0].X;
+        const firsty = this._points[0].Y;
+        const lastx = this._points[this._points.length - 2].X;
+        const lasty = this._points[this._points.length - 2].Y;
+        var fourth = (lastx - firstx) / 4;
+        if (isNaN(fourth) || fourth === 0) { fourth = 0.01; }
+        var m = (lasty - firsty) / (lastx - firstx);
+        if (isNaN(m) || m === 0) { m = 0.01; }
+        const b = firsty - m * firstx;
         if (shape === "noRec") {
             return false;
         }
@@ -724,6 +733,8 @@ export default class GestureOverlay extends Touchable {
 
                 this._points.push({ X: left, Y: top });
                 this._points.push({ X: left, Y: top });
+                // this._points.push({ X: left, Y: top });
+
                 // this._points.push({ X: left, Y: top });
                 // this._points.push({ X: left, Y: top });
 
@@ -797,8 +808,33 @@ export default class GestureOverlay extends Touchable {
 
                 break;
             case "line":
-                this._points.push({ X: left, Y: top });
-                this._points.push({ X: right, Y: bottom });
+                // const firstx = this._points[0].X;
+                // const firsty = this._points[0].Y;
+                // const lastx = this._points[this._points.length - 1].X;
+                // const lasty = this._points[this._points.length - 1].Y;
+                // const fourth = (lastx - firstx) / 4;
+                // const m = (lasty - firsty) / (lastx - firstx);
+                // const b = firsty - m * firstx;
+                this._points.push({ X: firstx, Y: firsty });
+                this._points.push({ X: firstx, Y: firsty });
+
+                this._points.push({ X: firstx + fourth, Y: m * (firstx + fourth) + b });
+                this._points.push({ X: firstx + fourth, Y: m * (firstx + fourth) + b });
+                this._points.push({ X: firstx + fourth, Y: m * (firstx + fourth) + b });
+                this._points.push({ X: firstx + fourth, Y: m * (firstx + fourth) + b });
+
+                this._points.push({ X: firstx + 2 * fourth, Y: m * (firstx + 2 * fourth) + b });
+                this._points.push({ X: firstx + 2 * fourth, Y: m * (firstx + 2 * fourth) + b });
+                this._points.push({ X: firstx + 2 * fourth, Y: m * (firstx + 2 * fourth) + b });
+                this._points.push({ X: firstx + 2 * fourth, Y: m * (firstx + 2 * fourth) + b });
+
+                this._points.push({ X: firstx + 3 * fourth, Y: m * (firstx + 3 * fourth) + b });
+                this._points.push({ X: firstx + 3 * fourth, Y: m * (firstx + 3 * fourth) + b });
+                this._points.push({ X: firstx + 3 * fourth, Y: m * (firstx + 3 * fourth) + b });
+                this._points.push({ X: firstx + 3 * fourth, Y: m * (firstx + 3 * fourth) + b });
+
+                this._points.push({ X: firstx + 4 * fourth, Y: m * (firstx + 4 * fourth) + b });
+                this._points.push({ X: firstx + 4 * fourth, Y: m * (firstx + 4 * fourth) + b });
                 break;
             case "arrow":
                 const x1 = left;
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 8e3f72cee..fe5bf1eb2 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -18,6 +18,8 @@ import { Doc } from "../../fields/Doc";
 import FormatShapePane from "./collections/collectionFreeForm/FormatShapePane";
 import { action } from "mobx";
 import { setupMoveUpEvents } from "../../Utils";
+import { undoBatch, UndoManager } from "../util/UndoManager";
+
 
 library.add(faPaintBrush);
 
@@ -26,8 +28,12 @@ const InkDocument = makeInterface(documentSchema);
 
 @observer
 export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocument>(InkDocument) {
+    private _controlUndo?: UndoManager.Batch;
+
     public static LayoutString(fieldStr: string) { return FieldView.LayoutString(InkingStroke, fieldStr); }
 
+
+
     private analyzeStrokes = () => {
         const data: InkData = Cast(this.dataDoc[this.fieldKey], InkField)?.inkData ?? [];
         CognitiveServices.Inking.Appliers.ConcatenateHandwriting(this.dataDoc, ["inkAnalysis", "handwriting"], [data]);
@@ -52,6 +58,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
     @action
     onControlDown = (e: React.PointerEvent, i: number): void => {
         setupMoveUpEvents(this, e, this.onControlMove, this.onControlup, (e) => { });
+        this._controlUndo = UndoManager.StartBatch("DocDecs set radius");
         this._prevX = e.clientX;
         this._prevY = e.clientY;
         this._controlNum = i;
@@ -76,6 +83,8 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
         this._prevX = 0;
         this._prevY = 0;
         this._controlNum = 0;
+        this._controlUndo?.end();
+        this._controlUndo = undefined;
     }
 
     public static MaskDim = 50000;
@@ -125,18 +134,17 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
             }
             handleLine.push({ X1: data[data.length - 2].X, Y1: data[data.length - 2].Y, X2: data[data.length - 1].X, Y2: data[data.length - 1].Y, X3: data[data.length - 1].X, Y3: data[data.length - 1].Y, dot1: data.length - 1, dot2: data.length - 1 });
 
-
-        }
-        if (data.length <= 4) {
-            handlePoints = [];
-            handleLine = [];
-            controlPoints = [];
-            for (var i = 0; i < data.length; i++) {
-                controlPoints.push({ X: data[i].X, Y: data[i].Y, I: i });
-            }
-
         }
-        const dotsize = String(Math.min(width * scaleX, height * scaleY) / 40);
+        // if (data.length <= 4) {
+        //     handlePoints = [];
+        //     handleLine = [];
+        //     controlPoints = [];
+        //     for (var i = 0; i < data.length; i++) {
+        //         controlPoints.push({ X: data[i].X, Y: data[i].Y, I: i });
+        //     }
+
+        // }
+        const dotsize = String(Math.max(width * scaleX, height * scaleY) / 40);
 
         const controls = controlPoints.map((pts, i) =>
 
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index a7d2c07fa..a1f5ff657 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -567,6 +567,8 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
                         style={{ backgroundColor: this._colorBtn ? "121212" : "", zIndex: 1001 }}>
                         {/* <FontAwesomeIcon icon="pen-nib" size="lg" /> */}
                         <div className="color-previewII" style={{ backgroundColor: color }} />
+                        {color === "" ? <p style={{ fontSize: 45, color: "red", marginTop: -16, marginLeft: -5, position: "fixed" }}>☒</p> : ""}
+
                     </button>)}
             </div>;
     }
@@ -580,7 +582,9 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
                     <button className="antimodeMenu-button" key={color}
                         onPointerDown={action(() => { this.changeColor(color, "fill"); this._fillBtn = false; this.editProperties(color, "fill"); })}
                         style={{ backgroundColor: this._fillBtn ? "121212" : "", zIndex: 1001 }}>
-                        <div className="color-previewII" style={{ backgroundColor: color }}></div>
+                        <div className="color-previewII" style={{ backgroundColor: color }}>
+                            {color === "" ? <p style={{ fontSize: 45, color: "red", marginTop: -16, marginLeft: -5, position: "fixed" }}>☒</p> : ""}
+                        </div>
                     </button>)}
 
             </div>;
diff --git a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
index 6263be261..d526033a0 100644
--- a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
+++ b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx
@@ -214,6 +214,7 @@ export default class FormatShapePane extends AntimodeMenu {
     @undoBatch
     @action
     control = (xDiff: number, yDiff: number, controlNum: number) => {
+        // console.log(controlNum, ink.length);
         this.selectedInk?.forEach(action(inkView => {
             if (this.selectedInk?.length === 1) {
                 const doc = Document(inkView.rootDoc);
@@ -221,6 +222,7 @@ export default class FormatShapePane extends AntimodeMenu {
                     const ink = Cast(doc.data, InkField)?.inkData;
                     if (ink) {
 
+
                         const newPoints: { X: number, Y: number }[] = [];
                         const order = controlNum % 4;
                         for (var i = 0; i < ink.length; i++) {
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index f5e0cd077..1c2f0e9e4 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -22,7 +22,7 @@ import { DocumentType } from "../../../documents/DocumentTypes";
 import FormatShapePane from "./FormatShapePane";
 import { SharingPermissions, GetEffectiveAcl } from "../../../../fields/util";
 import { InkField } from "../../../../fields/InkField";
-import { undoBatch } from "../../../util/UndoManager";
+import { undoBatch, UndoManager } from "../../../util/UndoManager";
 import { ColorState, SketchPicker } from "react-color";
 import AntimodeMenu from "../../AntimodeMenu";
 import "./FormatShapePane.scss";
@@ -39,6 +39,7 @@ interface PropertiesViewProps {
 
 @observer
 export class PropertiesView extends React.Component<PropertiesViewProps> {
+    private _widthUndo?: UndoManager.Batch;
 
     @computed get MAX_EMBED_HEIGHT() { return 200; }
 
@@ -59,6 +60,9 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @observable openAppearance: boolean = true;
     @observable openTransform: boolean = true;
 
+    @observable _controlBtn: boolean = false;
+    @observable _lock: boolean = false;
+
     @computed get isInk() { return this.selectedDoc?.type === DocumentType.INK; }
 
     @action
@@ -424,20 +428,19 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         }
     }
 
-    @observable _controlBtn: boolean = false;
-    @observable _lock: boolean = false;
+
 
     @computed
     get controlPointsButton() {
         return <div className="inking-button">
             <Tooltip title={<><div className="dash-tooltip">{"Edit points"}</div></>}>
-                <div className="inking-button-points" onPointerDown={action(() => this._controlBtn = !this._controlBtn)} style={{ backgroundColor: this._controlBtn ? "black" : "" }}>
+                <div className="inking-button-points" onPointerDown={action(() => FormatShapePane.Instance._controlBtn = !FormatShapePane.Instance._controlBtn)} style={{ backgroundColor: FormatShapePane.Instance._controlBtn ? "black" : "" }}>
                     <FontAwesomeIcon icon="bezier-curve" color="white" size="lg" />
                 </div>
             </Tooltip>
-            <Tooltip title={<><div className="dash-tooltip">{this._lock ? "Unlock points" : "Lock points"}</div></>}>
-                <div className="inking-button-lock" onPointerDown={action(() => this._lock = !this._lock)} >
-                    <FontAwesomeIcon icon={this._lock ? "unlock" : "lock"} color="white" size="lg" />
+            <Tooltip title={<><div className="dash-tooltip">{FormatShapePane.Instance._lock ? "Unlock ratio" : "Lock ratio"}</div></>}>
+                <div className="inking-button-lock" onPointerDown={action(() => FormatShapePane.Instance._lock = !FormatShapePane.Instance._lock)} >
+                    <FontAwesomeIcon icon={FormatShapePane.Instance._lock ? "lock" : "unlock"} color="white" size="lg" />
                 </div>
             </Tooltip>
             <Tooltip title={<><div className="dash-tooltip">{"Rotate 90˚"}</div></>}>
@@ -492,12 +495,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 const oldX = NumCast(this.selectedDoc?.x);
                 const oldY = NumCast(this.selectedDoc?.y);
                 this.selectedDoc && (this.selectedDoc._width = oldWidth + (dirs === "up" ? 10 : - 10));
-                this._lock && this.selectedDoc && (this.selectedDoc._height = (NumCast(this.selectedDoc?._width) / oldWidth * NumCast(this.selectedDoc?._height)));
+                FormatShapePane.Instance._lock && this.selectedDoc && (this.selectedDoc._height = (NumCast(this.selectedDoc?._width) / oldWidth * NumCast(this.selectedDoc?._height)));
                 const doc = this.selectedDoc;
                 if (doc?.type === DocumentType.INK && doc.x && doc.y && doc._height && doc._width) {
-                    console.log(doc.x, doc.y, doc._height, doc._width);
                     const ink = Cast(doc.data, InkField)?.inkData;
-                    console.log(ink);
                     if (ink) {
                         const newPoints: { X: number, Y: number }[] = [];
                         for (var j = 0; j < ink.length; j++) {
@@ -516,12 +517,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 const oX = NumCast(this.selectedDoc?.x);
                 const oY = NumCast(this.selectedDoc?.y);
                 this.selectedDoc && (this.selectedDoc._height = oHeight + (dirs === "up" ? 10 : - 10));
-                this._lock && this.selectedDoc && (this.selectedDoc._width = (NumCast(this.selectedDoc?._height) / oHeight * NumCast(this.selectedDoc?._width)));
+                FormatShapePane.Instance._lock && this.selectedDoc && (this.selectedDoc._width = (NumCast(this.selectedDoc?._height) / oHeight * NumCast(this.selectedDoc?._width)));
                 const docu = this.selectedDoc;
                 if (docu?.type === DocumentType.INK && docu.x && docu.y && docu._height && docu._width) {
-                    console.log(docu.x, docu.y, docu._height, docu._width);
                     const ink = Cast(docu.data, InkField)?.inkData;
-                    console.log(ink);
                     if (ink) {
                         const newPoints: { X: number, Y: number }[] = [];
                         for (var j = 0; j < ink.length; j++) {
@@ -556,17 +555,18 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     set shapeWid(value) {
         const oldWidth = NumCast(this.selectedDoc?._width);
         this.selectedDoc && (this.selectedDoc._width = Number(value));
-        this._lock && this.selectedDoc && (this.selectedDoc._height = (NumCast(this.selectedDoc?._width) * NumCast(this.selectedDoc?._height)) / oldWidth);
+        FormatShapePane.Instance._lock && this.selectedDoc && (this.selectedDoc._height = (NumCast(this.selectedDoc?._width) * NumCast(this.selectedDoc?._height)) / oldWidth);
     }
     set shapeHgt(value) {
         const oldHeight = NumCast(this.selectedDoc?._height);
         this.selectedDoc && (this.selectedDoc._height = Number(value));
-        this._lock && this.selectedDoc && (this.selectedDoc._width = (NumCast(this.selectedDoc?._height) * NumCast(this.selectedDoc?._width)) / oldHeight);
+        FormatShapePane.Instance._lock && this.selectedDoc && (this.selectedDoc._width = (NumCast(this.selectedDoc?._height) * NumCast(this.selectedDoc?._width)) / oldHeight);
     }
 
-    @computed get hgtInput() { return this.inputBoxDuo("hgt", this.shapeHgt, (val: string) => this.shapeHgt = val, "H:", "wid", this.shapeWid, (val: string) => this.shapeWid = val, "W:"); }
-    @computed get XpsInput() { return this.inputBoxDuo("Xps", this.shapeXps, (val: string) => this.shapeXps = val, "X:", "Yps", this.shapeYps, (val: string) => this.shapeYps = val, "Y:"); }
-    @computed get rotInput() { return this.inputBoxDuo("rot", this.shapeRot, (val: string) => { this.rotate(Number(val) - Number(this.shapeRot)); this.shapeRot = val; return true; }, "∠:", "rot", this.shapeRot, (val: string) => this.shapeRot = val, ""); }
+    @computed get hgtInput() { return this.inputBoxDuo("hgt", this.shapeHgt, (val: string) => { if (!isNaN(Number(val))) { this.shapeHgt = val; } return true; }, "H:", "wid", this.shapeWid, (val: string) => { if (!isNaN(Number(val))) { this.shapeWid = val; } return true; }, "W:"); }
+    @computed get XpsInput() { return this.inputBoxDuo("Xps", this.shapeXps, (val: string) => { if (val !== "0" && !isNaN(Number(val))) { this.shapeXps = val; } return true; }, "X:", "Yps", this.shapeYps, (val: string) => { if (val !== "0" && !isNaN(Number(val))) { this.shapeYps = val; } return true; }, "Y:"); }
+    @computed get rotInput() { return this.inputBoxDuo("rot", this.shapeRot, (val: string) => { if (!isNaN(Number(val))) { this.rotate(Number(val) - Number(this.shapeRot)); this.shapeRot = val; } return true; }, "∠:", "rot", this.shapeRot, (val: string) => { if (!isNaN(Number(val))) { this.rotate(Number(val) - Number(this.shapeRot)); this.shapeRot = val; } return true; }, ""); }
+
 
     @observable private _fillBtn = false;
     @observable private _lineBtn = false;
@@ -683,7 +683,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 </div>
                 <input className="width-range" type="range"
                     defaultValue={Number(this.widthStk)} min={1} max={100}
-                    onChange={undoBatch(action((e) => this.widthStk = e.target.value))} />
+                    onChange={(action((e) => this.widthStk = e.target.value))}
+                    onMouseDown={(e) => { this._widthUndo = UndoManager.StartBatch("width undo");; }}
+                    onMouseUp={(e) => { this._widthUndo?.end(); this._widthUndo = undefined; }}
+                />
             </div>
 
             <div className="arrows">
@@ -701,7 +704,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 </div>
             </div>
             <div className="dashed">
-                <div className="dashed-title">Dash:</div>
+                <div className="dashed-title">Dashed Line:</div>
                 <input key="markHead" className="dashed-input"
                     type="checkbox" checked={this.dashdStk === "2"}
                     onChange={this.changeDash} />
-- 
cgit v1.2.3-70-g09d2


From 0d6a6991ae39406f80530bcaaa6e5b328bd64b67 Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Wed, 5 Aug 2020 12:59:07 -0500
Subject: UI changes and bug fixes found with UV

---
 src/client/util/CurrentUserUtils.ts                |  3 ++-
 src/client/util/SettingsManager.scss               | 20 ++++++++++++----
 src/client/util/SettingsManager.tsx                | 13 +++++-----
 src/client/views/MainView.tsx                      |  7 ++++++
 src/client/views/MainViewModal.tsx                 |  6 +----
 src/client/views/PropertiesButtons.tsx             | 28 +++++++++++++++++-----
 src/client/views/collections/CollectionMenu.tsx    |  9 +++----
 .../collectionFreeForm/PropertiesView.tsx          |  3 +--
 8 files changed, 60 insertions(+), 29 deletions(-)

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

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 95e02b5fd..630952ccf 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -8,7 +8,7 @@ import { Doc, DocListCast, DocListCastAsync, DataSym } from "../../fields/Doc";
 import { List } from "../../fields/List";
 import { listSpec } from "../../fields/Schema";
 import { ScriptField, ComputedField } from "../../fields/ScriptField";
-import { Cast, PromiseValue, StrCast, NumCast } from "../../fields/Types";
+import { Cast, PromiseValue, StrCast, NumCast, BoolCast } from "../../fields/Types";
 import { nullAudio } from "../../fields/URLField";
 import { DragManager } from "./DragManager";
 import { Scripting } from "./Scripting";
@@ -891,6 +891,7 @@ export class CurrentUserUtils {
         doc.fontColor = StrCast(doc.fontColor, "black");
         doc.fontHighlight = StrCast(doc.fontHighlight, "");
         doc.defaultColor = StrCast(doc.defaultColor, "white");
+        doc.noviceMode = BoolCast(doc.noviceMode, true);
         doc["constants-snapThreshold"] = NumCast(doc["constants-snapThreshold"], 10); //
         doc["constants-dragThreshold"] = NumCast(doc["constants-dragThreshold"], 4); //
         Utils.DRAG_THRESHOLD = NumCast(doc["constants-dragThreshold"]);
diff --git a/src/client/util/SettingsManager.scss b/src/client/util/SettingsManager.scss
index 2a4a4241c..41bce8a1b 100644
--- a/src/client/util/SettingsManager.scss
+++ b/src/client/util/SettingsManager.scss
@@ -25,8 +25,15 @@
 .settings-title {
     font-size: 25px;
     font-weight: bold;
+    padding-right: 10px;
+    color: black;
+}
+
+.settings-username {
+    font-size: 14px;
     padding-right: 15px;
     color: black;
+    margin-top: 10px;
 }
 
 .settings-section {
@@ -94,7 +101,7 @@
         color: black;
         border-radius: 5px;
 
-        &:hover{
+        &:hover {
             cursor: pointer;
         }
     }
@@ -104,7 +111,8 @@
 
         .playground-check {
             margin-right: 5px;
-            &:hover{
+
+            &:hover {
                 cursor: pointer;
             }
         }
@@ -119,7 +127,7 @@
     margin-top: 2px;
     margin-right: 25px;
 
-    &:hover{
+    &:hover {
         cursor: pointer;
     }
 
@@ -162,7 +170,8 @@
             font-size: 9;
             margin-right: 6;
             border-radius: 5px;
-            &:hover{
+
+            &:hover {
                 cursor: pointer;
             }
         }
@@ -172,7 +181,8 @@
             color: black;
             font-size: 9;
             border-radius: 5px;
-            &:hover{
+
+            &:hover {
                 cursor: pointer;
             }
         }
diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index a12cc2cb6..fce28a466 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -147,9 +147,9 @@ export default class SettingsManager extends React.Component<{}> {
 
         const passwordContent = <div className="password-content">
             <div className="password-content-inputs">
-                <input className="password-inputs" placeholder="current password" ref={this.curr_password_ref} />
-                <input className="password-inputs" placeholder="new password" ref={this.new_password_ref} />
-                <input className="password-inputs" placeholder="confirm new password" ref={this.new_confirm_ref} />
+                <input className="password-inputs" type="password" placeholder="current password" ref={this.curr_password_ref} />
+                <input className="password-inputs" type="password" placeholder="new password" ref={this.new_password_ref} />
+                <input className="password-inputs" type="password" placeholder="confirm new password" ref={this.new_confirm_ref} />
             </div>
             <div className="password-content-buttons">
                 {this.errorText ? <div className="error-text">{this.errorText}</div> : undefined}
@@ -233,7 +233,9 @@ export default class SettingsManager extends React.Component<{}> {
         return (<div className="settings-interface">
             <div className="settings-top">
                 <div className="settings-title">Settings</div>
-                <button onClick={() => window.location.assign(Utils.prepend("/logout"))}>
+                <div className="settings-username">{Doc.CurrentUserEmail}</div>
+                <button onClick={() => window.location.assign(Utils.prepend("/logout"))}
+                    style={{ right: 35, position: "absolute" }} >
                     {CurrentUserUtils.GuestWorkspace ? "Exit" : "Log Out"}
                 </button>
                 <div className="close-button" onClick={this.close}>
@@ -268,8 +270,7 @@ export default class SettingsManager extends React.Component<{}> {
                 isDisplayed={this.isOpen}
                 interactive={true}
                 closeOnExternalClick={this.close}
-                width={600}
-                height={340}
+                dialogueBoxStyle={{ width: "600px", height: "340px" }}
             />
         );
     }
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index bbf36a04f..4bbcddd79 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -315,6 +315,12 @@ export class MainView extends React.Component {
         if (this.panelContent === doc?.title) return "lightgrey";
 
         if (doc?.type === DocumentType.COL) {
+            if (doc.title === "Basic Item Creators" || doc.title === "sidebar-tools"
+                || doc.title === "sidebar-recentlyClosed" || doc.title === "sidebar-catalog"
+                || doc.title === "Mobile Uploads" || doc.title === "COLLECTION_PROTO"
+                || doc.title === "Advanced Item Prototypes" || doc.title === "all Creators") {
+                return "lightgrey";
+            }
             return StrCast(Doc.UserDoc().defaultColor);
         }
         if (this.darkScheme) {
@@ -450,6 +456,7 @@ export class MainView extends React.Component {
                     ContainingCollectionView={undefined}
                     ContainingCollectionDoc={undefined}
                     relative={true}
+                    forcedBackgroundColor={() => "lightgrey"}
                 />
             </div>
             {this.docButtons}</div>;
diff --git a/src/client/views/MainViewModal.tsx b/src/client/views/MainViewModal.tsx
index c7b752b60..19387f619 100644
--- a/src/client/views/MainViewModal.tsx
+++ b/src/client/views/MainViewModal.tsx
@@ -10,8 +10,6 @@ export interface MainViewOverlayProps {
     overlayStyle?: React.CSSProperties;
     dialogueBoxDisplayedOpacity?: number;
     overlayDisplayedOpacity?: number;
-    width?: number;
-    height?: number;
     closeOnExternalClick?: () => void; // the close method of a MainViewModal, triggered if there is a click on the overlay (closing the modal)
 }
 
@@ -31,9 +29,7 @@ export default class MainViewModal extends React.Component<MainViewOverlayProps>
                     style={{
                         borderColor: "black",
                         ...(p.dialogueBoxStyle || {}),
-                        opacity: p.isDisplayed ? dialogueOpacity : 0,
-                        width: this.props.width ? this.props.width : "auto",
-                        height: this.props.height ? this.props.height : "auto"
+                        opacity: p.isDisplayed ? dialogueOpacity : 0
                     }}
                 >{p.contents}</div>
                 <div
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index c25d58c60..14ea36dde 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -196,6 +196,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
                         }
                     }}>
                     <FontAwesomeIcon className="documentdecorations-icon" size="lg"
+                        color="black"
                         style={{ WebkitAnimation: animation, MozAnimation: animation }}
                         icon={(() => {
                             switch (this.openHover) {
@@ -207,7 +208,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
                         })()}
                     />
                 </div>
-                <div className="propertiesButtons-title">Fetch</div>
+                <div className="propertiesButtons-title" style={{ backgroundColor: "white", color: "black" }}>Fetch</div>
             </div>
         </Tooltip>;
     }
@@ -226,7 +227,11 @@ export class PropertiesButtons extends React.Component<{}, {}> {
                     />
                 </div>
 
-                <div className="propertiesButtons-title">{Doc.isDocPinned(targetDoc) ? "Unpin" : "Pin"}</div>
+                <div className="propertiesButtons-title" style={{
+                    backgroundColor: Doc.isDocPinned(targetDoc) ? "white" : "black",
+                    color: Doc.isDocPinned(targetDoc) ? "black" : "white"
+                }}
+                >{Doc.isDocPinned(targetDoc) ? "Unpin" : "Pin"}</div>
             </div>
         </Tooltip>;
     }
@@ -339,11 +344,16 @@ export class PropertiesButtons extends React.Component<{}, {}> {
                 "Unlock Position" : "Lock Position"}</div></>} placement="top">
             <div>
                 <div className={"propertiesButtons-linkButton-empty"}
+                    style={{ backgroundColor: BoolCast(this.selectedDoc?.lockedPosition) ? "white" : "" }}
                     onPointerDown={this.onLock} >
                     {<FontAwesomeIcon className="documentdecorations-icon"
+                        color={BoolCast(this.selectedDoc?.lockedPosition) ? "black" : "white"}
                         icon={BoolCast(this.selectedDoc?.lockedPosition) ? "unlock" : "lock"} size="lg" />}
                 </div>
-                <div className="propertiesButtons-title">Position </div>
+                <div className="propertiesButtons-title" style={{
+                    backgroundColor: BoolCast(this.selectedDoc?.lockedPosition) ? "white" : "black",
+                    color: BoolCast(this.selectedDoc?.lockedPosition) ? "black" : "white"
+                }}>Position </div>
             </div>
         </Tooltip>;
     }
@@ -535,13 +545,16 @@ export class PropertiesButtons extends React.Component<{}, {}> {
             title={<><div className="dash-tooltip">{this.selectedDoc?.useClusters ? "Stop Showing Clusters" : "Show Clusters"}</div></>} placement="top">
             <div>
                 <div className={"propertiesButtons-linkButton-empty"}
-                    style={{ backgroundColor: this.selectedDoc?.useClusters ? "#a0a0a0" : "" }}
+                    style={{ backgroundColor: this.selectedDoc?.useClusters ? "white" : "" }}
                     onPointerDown={this.changeClusters}>
                     {<FontAwesomeIcon className="documentdecorations-icon"
                         color={this.selectedDoc?.useClusters ? "black" : "white"}
                         icon="braille" size="lg" />}
                 </div>
-                <div className="propertiesButtons-title"> clusters </div>
+                <div className="propertiesButtons-title" style={{
+                    backgroundColor: this.selectedDoc?.useClusters ? "white" : "black",
+                    color: this.selectedDoc?.useClusters ? "black" : "white"
+                }}> clusters </div>
             </div>
         </Tooltip>;
     }
@@ -569,7 +582,10 @@ export class PropertiesButtons extends React.Component<{}, {}> {
                         color={this.selectedDoc?._fitToBox ? "black" : "white"}
                         icon="expand" size="lg" />}
                 </div>
-                <div className="propertiesButtons-title"> {this.selectedDoc?._fitToBox ? "unfit" : "fit"} </div>
+                <div className="propertiesButtons-title" style={{
+                    backgroundColor: this.selectedDoc?._fitToBox ? "white" : "black",
+                    color: this.selectedDoc?._fitToBox ? "black" : "white"
+                }}> {this.selectedDoc?._fitToBox ? "unfit" : "fit"} </div>
             </div>
         </Tooltip>;
     }
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 511735f2d..6eed4eba1 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -673,15 +673,16 @@ export class CollectionStackingViewChrome extends React.Component<CollectionMenu
             if (docs instanceof Doc) {
                 const keys = Object.keys(docs).filter(key => key.indexOf("title") >= 0 || key.indexOf("author") >= 0 ||
                     key.indexOf("creationDate") >= 0 || key.indexOf("lastModified") >= 0 ||
-                    (key[0].toUpperCase() === key[0] && key.substring(0, 3) !== "ACL"));
-                return keys.filter(key => key.toLowerCase().startsWith(value));
+                    (key[0].toUpperCase() === key[0] && key.substring(0, 3) !== "ACL" && key !== "UseCors" && key[0] !== "_"));
+                return keys.filter(key => key.toLowerCase().indexOf(value.toLowerCase()) > -1);
             } else {
                 const keys = new Set<string>();
                 docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key)));
                 const noviceKeys = Array.from(keys).filter(key => key.indexOf("title") >= 0 ||
                     key.indexOf("author") >= 0 || key.indexOf("creationDate") >= 0 ||
-                    key.indexOf("lastModified") >= 0 || (key[0].toUpperCase() === key[0] && key.substring(0, 3) !== "ACL"));
-                return noviceKeys.filter(key => key.toLowerCase().startsWith(value));
+                    key.indexOf("lastModified") >= 0 || (key[0].toUpperCase() === key[0] &&
+                        key.substring(0, 3) !== "ACL" && key !== "UseCors" && key[0] !== "_"));
+                return noviceKeys.filter(key => key.toLowerCase().indexOf(value.toLowerCase()) > -1);
             }
         }
 
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index a6b1849b1..7f21c63da 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -161,7 +161,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
             doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key));
             const rows: JSX.Element[] = [];
             for (const key of Object.keys(ids).slice().sort()) {
-                if ((key[0] === key[0].toUpperCase() && key.substring(0, 3) !== "ACL")
+                if ((key[0] === key[0].toUpperCase() && key.substring(0, 3) !== "ACL" && key !== "UseCors")
                     || key[0] === "#" || key === "author" ||
                     key === "creationDate" || key.indexOf("lastModified") !== -1) {
 
@@ -354,7 +354,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         />;
     }
 
-    @undoBatch
     @action
     toggleCheckbox = () => {
         this.layoutFields = !this.layoutFields;
-- 
cgit v1.2.3-70-g09d2


From 94a97864c657a546965df32fa30900600fa8084b Mon Sep 17 00:00:00 2001
From: anika-ahluwalia <anika.ahluwalia@gmail.com>
Date: Wed, 5 Aug 2020 15:42:51 -0500
Subject: UI consistencies

---
 src/client/views/MainView.scss                                     | 4 +++-
 src/client/views/MainView.tsx                                      | 7 ++++---
 .../views/collections/collectionFreeForm/PropertiesView.scss       | 3 ++-
 src/client/views/collections/collectionFreeForm/PropertiesView.tsx | 1 +
 4 files changed, 10 insertions(+), 5 deletions(-)

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

diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index e9e700ba8..388d4b369 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -103,7 +103,8 @@
 }
 
 .mainView-propertiesDragger {
-    background-color: rgb(140, 139, 139);
+    //background-color: rgb(140, 139, 139);
+    background-color: lightgrey;
     height: 55px;
     width: 17px;
     position: absolute;
@@ -298,6 +299,7 @@
     position: absolute;
     z-index: 2;
     touch-action: none;
+    background-color: lightgrey;
     cursor: grab;
 
     .mainView-libraryHandle-icon {
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 4bbcddd79..a6a33d9f7 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -564,7 +564,8 @@ export class MainView extends React.Component {
                 <div className="mainView-flyoutContainer" style={{ width: this.flyoutWidth }}>
                     {this.flyoutWidth !== 0 ? <div className="mainView-libraryHandle"
                         onPointerDown={this.onFlyoutPointerDown}
-                        style={{ backgroundColor: '#8c8b8b' }}>
+                    //style={{ backgroundColor: '#8c8b8b' }}
+                    >
                         <span title="library View Dragger" style={{
                             width: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "100%" : "3vw",
                             //height: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "100%" : "100vh",
@@ -572,7 +573,7 @@ export class MainView extends React.Component {
                             top: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "" : "0"
                         }} />
                         <div className="mainview-libraryHandle-icon">
-                            <FontAwesomeIcon icon="chevron-left" color="white" size="sm" />
+                            <FontAwesomeIcon icon="chevron-left" color="black" size="sm" />
                         </div>
                     </div> : null}
                     <div className="mainView-libraryFlyout" style={{
@@ -591,7 +592,7 @@ export class MainView extends React.Component {
                     <div className="mainView-propertiesDragger" title="Properties View Dragger" onPointerDown={this.onPropertiesPointerDown}
                         style={{ right: rightFlyout, top: "50%" }}>
                         <div className="mainView-propertiesDragger-icon">
-                            <FontAwesomeIcon icon={this.propertiesIcon} color="white" size="sm" /> </div>
+                            <FontAwesomeIcon icon={this.propertiesIcon} color="black" size="sm" /> </div>
                     </div>
                 }
                 {this.propertiesWidth() < 10 ? (null) :
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index 9560de2f5..71b6d3ce9 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -596,6 +596,7 @@
 
         display: flex;
         margin-bottom: 3px;
+        margin-left: 4px;
 
         .arrows-head {
 
@@ -629,7 +630,7 @@
     .dashed {
 
         display: flex;
-        margin-left: 74px;
+        margin-left: 64px;
         margin-bottom: 6px;
 
         .dashed-title {
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 8b78a05fe..a67f53cea 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -267,6 +267,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                     bringToFront={returnFalse}
                     ContentScaling={returnOne}
                     dontRegisterView={true}
+                    dropAction={undefined}
                 />
             </div>;
         } else {
-- 
cgit v1.2.3-70-g09d2


From fa0b28c300416621dec25407484fc2606a736e2a Mon Sep 17 00:00:00 2001
From: Geireann Lindfield Roberts <60007097+geireann@users.noreply.github.com>
Date: Thu, 6 Aug 2020 05:11:18 +0800
Subject: automatic text progressivize, ui changes, bug fixes

---
 src/client/documents/Documents.ts                  |   2 +
 src/client/views/PropertiesButtons.tsx             |  37 ++-
 .../views/collections/CollectionDockingView.scss   |   8 +-
 .../views/collections/CollectionDockingView.tsx    |   2 +-
 .../views/collections/CollectionStackingView.tsx   |  12 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   4 +-
 .../collectionFreeForm/PropertiesView.tsx          |   4 +-
 .../views/nodes/CollectionFreeFormDocumentView.tsx |  20 +-
 src/client/views/nodes/PresBox.scss                |  56 +++-
 src/client/views/nodes/PresBox.tsx                 | 337 ++++++++-------------
 .../views/nodes/formattedText/FormattedTextBox.tsx |  65 ++++
 .../views/presentationview/PresElementBox.scss     |  35 ++-
 .../views/presentationview/PresElementBox.tsx      |  49 ++-
 13 files changed, 386 insertions(+), 245 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 539341b62..57fcf3a00 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -129,6 +129,7 @@ export interface DocumentOptions {
     isLinkButton?: boolean;
     _columnWidth?: number;
     _fontSize?: string;
+    _fontWeight?: number;
     _fontFamily?: string;
     curPage?: number;
     currentTimecode?: number; // the current timecode of a time-based document (e.g., current time of a video)  value is in seconds
@@ -139,6 +140,7 @@ export interface DocumentOptions {
     appearFrame?: number; // the frame in which the document appears
     presTransition?: number; //the time taken for the transition TO a document
     presDuration?: number; //the duration of the slide in presentation view
+    presProgressivize?: boolean;
     // xArray?: number[];
     // yArray?: number[];
     borderRounding?: string;
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index d46c03470..7d8a75dda 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -30,6 +30,7 @@ import { undoBatch, UndoManager } from '../util/UndoManager';
 import { DocumentType } from '../documents/DocumentTypes';
 import { CollectionFreeFormView } from './collections/collectionFreeForm/CollectionFreeFormView';
 import { InkField } from '../../fields/InkField';
+import { PresBox } from './nodes/PresBox';
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -209,13 +210,44 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         const isPinned = targetDoc && Doc.isDocPinned(targetDoc);
         return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}</div></>}>
             <div className="propertiesButtons-linker"
-                style={{ backgroundColor: isPinned ? "white" : "", color: isPinned ? "black" : "white" }}
+                style={{ backgroundColor: isPinned ? "" : "white", color: isPinned ? "white" : "black" }}
                 onClick={e => DockedFrameRenderer.PinDoc(targetDoc, isPinned)}>
                 <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin"
                 />
             </div></Tooltip>;
     }
 
+    @computed
+    get pinWithViewButton() {
+        const targetDoc = this.selectedDoc;
+        const isPinned = targetDoc && Doc.isDocPinned(targetDoc);
+        if (targetDoc) {
+            const x = targetDoc._panX;
+            const y = targetDoc._panY;
+            const scale = targetDoc._viewScale;
+        }
+        return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{"Pin with this view"}</div></>}>
+            <div className="propertiesButtons-linker"
+                style={{ backgroundColor: "white", color: "black" }}
+                onClick={e => {
+                    if (targetDoc) {
+                        DockedFrameRenderer.PinDoc(targetDoc, false);
+                        const activeDoc = PresBox.Instance.childDocs[PresBox.Instance.childDocs.length - 1];
+                        const x = targetDoc._panX;
+                        const y = targetDoc._panY;
+                        const scale = targetDoc._viewScale;
+                        activeDoc.presPinView = true;
+                        activeDoc.presPinViewX = x;
+                        activeDoc.presPinViewY = y;
+                        activeDoc.presPinViewScale = scale;
+                    }
+                }}>
+                <div style={{ position: 'absolute', fontSize: 25, fontWeight: 700, transform: 'translate(42%, -7px)', color: 'rgba(0,0,0,0.2)' }}>V</div>
+                <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin" />
+            </div></Tooltip>;
+    }
+
+
     @computed
     get metadataButton() {
         //const view0 = this.view0;
@@ -607,6 +639,9 @@ export class PropertiesButtons extends React.Component<{}, {}> {
             <div className="propertiesButtons-button">
                 {this.pinButton}
             </div>
+            <div className="propertiesButtons-button">
+                {this.pinWithViewButton}
+            </div>
             <div className="propertiesButtons-button">
                 {this.copyButton}
             </div>
diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss
index 857f751d3..98babc3d2 100644
--- a/src/client/views/collections/CollectionDockingView.scss
+++ b/src/client/views/collections/CollectionDockingView.scss
@@ -45,7 +45,7 @@
 
         .miniPres-button-text {
             display: flex;
-            height: 30;
+            height: 20;
             font-weight: 400;
             min-width: 100%;
             border-radius: 5px;
@@ -55,15 +55,15 @@
         }
 
         .miniPres-divider {
-            width: 1px;
+            width: 0.5px;
             height: 80%;
             border-right: solid 2px #5a5a5a;
         }
 
         .miniPres-button {
             display: flex;
-            height: 30;
-            min-width: 30;
+            height: 20;
+            min-width: 20;
             border-radius: 100%;
             align-items: center;
             justify-content: center;
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 9c85bd0a2..bc88236dd 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -871,7 +871,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
     }
     renderMiniPres() {
         return <div className="miniPres" style={{
-            width: 400, height: 50, background: '#323232'
+            width: 250, height: 30, background: '#323232'
         }}>
             <div className="miniPresOverlay" >
                 <div className="miniPres-button" onClick={PresBox.Instance.back}><FontAwesomeIcon icon={"arrow-left"} /></div>
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index e00bdb065..fe3d57bdb 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -184,7 +184,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument)
         if (found) {
             const top = found.getBoundingClientRect().top;
             const localTop = this.props.ScreenToLocalTransform().transformPoint(0, top);
-            smoothScroll(doc.presTransition ? Number(doc.presTransition) : 500, this._mainCont!, localTop[1] + this._mainCont!.scrollTop);
+            smoothScroll(doc.presTransition || doc.presTransition === 0 ? NumCast(doc.presTransition) : 500, this._mainCont!, localTop[1] + this._mainCont!.scrollTop);
         }
         afterFocus && setTimeout(() => {
             if (afterFocus?.()) { }
@@ -291,20 +291,19 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument)
                 const docs = this.childDocList;
                 if (docs) {
                     newDocs.map((doc, i) => {
+                        console.log(doc.title);
                         if (i === 0) {
                             if (targInd === -1) targInd = docs.length;
                             else targInd = docs.indexOf(this.filteredChildren[targInd]);
                             const srcInd = docs.indexOf(doc);
                             docs.splice(srcInd, 1);
                             docs.splice((targInd > srcInd ? targInd - 1 : targInd) + plusOne, 0, doc);
-                        } else {
+                        } else if (i < (newDocs.length / 2)) { //glr: for some reason dragged documents are duplicated
                             if (targInd === -1) targInd = docs.length;
-                            else targInd = docs.indexOf(this.filteredChildren[targInd]);
+                            else targInd = docs.indexOf(newDocs[0]) + 1;
                             const srcInd = docs.indexOf(doc);
-                            const firstInd = docs.indexOf(newDocs[0]);
                             docs.splice(srcInd, 1);
-                            // docs.splice((targInd > srcInd ? targInd - 1 : targInd) + plusOne, 0, doc);
-                            docs.splice(firstInd + 1, 0, doc);
+                            docs.splice((targInd > srcInd ? targInd - 1 : targInd) + plusOne, 0, doc);
                         }
                     });
                 }
@@ -312,6 +311,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument)
         }
         return false;
     }
+
     @undoBatch
     @action
     onExternalDrop = async (e: React.DragEvent): Promise<void> => {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 109808956..65cd28742 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -911,8 +911,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
             //     !doc.z && NumCast(this.layoutDoc.scale) < 1 && this.scaleAtPt(DocumentView._focusHack, 1); // [NumCast(doc.x), NumCast(doc.y)], 1);
             // } else {
             if (DocListCast(this.dataDoc[this.props.fieldKey]).includes(doc)) {
-                // glr: freeform transform speed can be set through user by adjusting for presentation transform
-                if (!doc.z) this.setPan(newPanX, newPanY, doc.presTransition ? `transform ${doc.presTransition}ms` : "transform 500ms", true); // docs that are floating in their collection can't be panned to from their collection -- need to propagate the pan to a parent freeform somehow
+                // glr: freeform transform speed can be set by adjusting presTransition field - needs a way of knowing when presentation is not active...
+                if (!doc.z) this.setPan(newPanX, newPanY, doc.presTransition || doc.presTransition === 0 ? `transform ${doc.presTransition}ms` : "transform 500ms", true); // docs that are floating in their collection can't be panned to from their collection -- need to propagate the pan to a parent freeform somehow
             }
             Doc.BrushDoc(this.props.Document);
             this.props.focus(this.props.Document);
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 1f66d4144..035cd938e 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -865,7 +865,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         if (this.isPres) {
             return <div className="propertiesView" style={{ width: this.props.width }} >
                 <div className="propertiesView-title" style={{ width: this.props.width }}>
-                    Presentation Toolbar
+                    Presentation
                 <div className="propertiesView-title-icon" onPointerDown={this.props.onDown}>
                         <FontAwesomeIcon icon="times" color="black" size="sm" />
                     </div>
@@ -922,7 +922,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                     <div className="propertiesView-sharing-title"
                         onPointerDown={() => runInAction(() => { this.openSlideOptions = !this.openSlideOptions; })}
                         style={{ backgroundColor: this.openSlideOptions ? "black" : "" }}>
-                        <FontAwesomeIcon icon={"cog"} /> &nbsp; {PresBox.Instance.stringType} options
+                        &nbsp; <FontAwesomeIcon icon={"cog"} /> &nbsp; {PresBox.Instance.stringType} options
                     <div className="propertiesView-sharing-title-icon">
                             <FontAwesomeIcon icon={this.openSlideOptions ? "caret-down" : "caret-right"} size="lg" color="white" />
                         </div>
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index c29547eac..35ed6c5a5 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -107,6 +107,15 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
         d["w-indexed"] = new List<number>(windexed);
         d["opacity-indexed"] = new List<number>(oindexed);
         d["scroll-indexed"] = new List<number>(scrollIndexed);
+        if (d.appearFrame) {
+            if (d.appearFrame === timecode + 1) {
+                d["text-color"] = "red";
+            } else if (d.appearFrame < timecode + 1) {
+                d["text-color"] = "grey";
+            } else { d["text-color"] = "black"; }
+        } else if (d.appearFrame === 0) {
+            d["text-color"] = "black";
+        }
     }
 
     public static updateScrollframe(doc: Doc, time: number) {
@@ -139,6 +148,15 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
             xindexed?.length <= timecode + 1 && xindexed.push(undefined as any as number);
             yindexed?.length <= timecode + 1 && yindexed.push(undefined as any as number);
             opacityindexed?.length <= timecode + 1 && opacityindexed.push(undefined as any as number);
+            if (doc.appearFrame) {
+                if (doc.appearFrame === timecode + 1) {
+                    doc["text-color"] = "red";
+                } else if (doc.appearFrame < timecode + 1) {
+                    doc["text-color"] = "grey";
+                } else { doc["text-color"] = "black"; }
+            } else if (doc.appearFrame === 0) {
+                doc["text-color"] = "black";
+            }
             doc.dataTransition = "all 1s";
         });
         setTimeout(() => docs.forEach(doc => doc.dataTransition = "inherit"), 1010);
@@ -166,7 +184,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
 
     public static setupKeyframes(docs: Doc[], timecode: number, progressivize: boolean = false) {
         docs.forEach((doc, i) => {
-            if (!doc.appearFrame) doc.appearFrame = i;
+            if (doc.appearFrame === undefined) doc.appearFrame = i;
             const curTimecode = progressivize ? i : timecode;
             const xlist = new List<number>(numberRange(timecode + 1).map(i => undefined) as any as number[]);
             const ylist = new List<number>(numberRange(timecode + 1).map(i => undefined) as any as number[]);
diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss
index 089f69873..16821f5bc 100644
--- a/src/client/views/nodes/PresBox.scss
+++ b/src/client/views/nodes/PresBox.scss
@@ -754,8 +754,6 @@
     }
 
     .presBox-button {
-        margin-right: 2.5px;
-        margin-left: 2.5px;
         height: 25px;
         border-radius: 5px;
         display: none;
@@ -787,13 +785,65 @@
         min-width: 100px;
         width: 100px;
         position: absolute;
-        right: 8px;
+        right: 10px;
 
         .present-icon {
             margin-right: 7px;
         }
     }
 
+        
+    .miniPresOverlay {
+        background-color: #323232;
+        color: white;
+        border-radius: 5px;
+        grid-template-rows: 100%;
+        height: 25;
+        width: 200;
+        justify-content: space-evenly;
+        align-items: center;
+        display: flex;
+        position: absolute;
+        right: 10px;
+
+        .miniPres-button-text {
+            display: flex;
+            height: 20;
+            width: max-content;
+            font-family: Roboto;
+            font-weight: 400;
+            letter-spacing: normal;
+            border-radius: 5px;
+            align-items: center;
+            justify-content: center;
+            transition: all 0.3s;
+        }
+
+        .miniPres-divider {
+            width: 0.5px;
+            height: 80%;
+            border-right: solid 1px #5a5a5a;
+        }
+
+        .miniPres-button {
+            display: flex;
+            height: 20;
+            min-width: 20;
+            border-radius: 100%;
+            align-items: center;
+            justify-content: center;
+            transition: all 0.3s;
+        }
+
+        .miniPres-button:hover {
+            background-color: #5a5a5a;
+        }
+
+        .miniPres-button-text:hover {
+            background-color: #5a5a5a;
+        }
+    }
+
 
 
     .collectionViewBaseChrome-viewPicker {
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index 2389d3875..1caefdc57 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -97,7 +97,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
     @action
     next = () => {
         this.updateCurrentPresentation();
+        const activeNext = Cast(this.childDocs[this.itemIndex + 1], Doc, null);
         const presTargetDoc = Cast(this.childDocs[this.itemIndex].presentationTargetDoc, Doc, null);
+        const childDocs = DocListCast(presTargetDoc[Doc.LayoutFieldKey(presTargetDoc)]);
+        const currentFrame = Cast(presTargetDoc.currentFrame, "number", null);
         const lastFrame = Cast(presTargetDoc.lastFrame, "number", null);
         const curFrame = NumCast(presTargetDoc.currentFrame);
         let internalFrames: boolean = false;
@@ -107,8 +110,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
             presTargetDoc._viewTransition = "all 1s";
             setTimeout(() => presTargetDoc._viewTransition = undefined, 1010);
             presTargetDoc.currentFrame = curFrame + 1;
+            if (presTargetDoc.scrollProgressivize) CollectionFreeFormDocumentView.updateScrollframe(presTargetDoc, currentFrame);
+            if (presTargetDoc.presProgressivize) CollectionFreeFormDocumentView.updateKeyframe(childDocs, currentFrame || 0);
             if (presTargetDoc.zoomProgressivize) this.zoomProgressivizeNext(presTargetDoc);
-            // Case 2: No more frames in current doc and next slide is defined, therefore move to next slide
+            // Case 2: Audio or video therefore wait to play the audio or video before moving on
         } else if ((presTargetDoc.type === DocumentType.VID || presTargetDoc.type === DocumentType.AUDIO) && !this._moveOnFromAudio) {
             if (presTargetDoc.type === DocumentType.AUDIO) {
                 AudioBox.Instance.playFrom(0);
@@ -117,7 +122,15 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
             if (presTargetDoc.type === DocumentType.VID) {
                 this._moveOnFromAudio = true;
             }
-        } else if (this.childDocs[this.itemIndex + 1] !== undefined) {
+            // Case 3: No more frames in current doc and next slide is defined, therefore move to next slide
+        } else if (activeNext !== undefined) {
+            if (!presTargetDoc.presProgressivize) {
+                const nextTagDoc = Cast(this.childDocs[this.itemIndex + 1].presentationTargetDoc, Doc, null);
+                const nextChildDocs = DocListCast(nextTagDoc[Doc.LayoutFieldKey(presTargetDoc)]);
+                nextChildDocs.forEach((doc, i) => {
+                    doc.opacity = 1;
+                })
+            }
             const nextSelected = this.itemIndex + 1;
             this.gotoDocument(nextSelected, this.itemIndex);
             this._moveOnFromAudio = false;
@@ -130,15 +143,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         this.updateCurrentPresentation();
         const docAtCurrent = this.childDocs[this.itemIndex];
         if (docAtCurrent) {
-            //check if any of the group members had used zooming in including the current document
-            //If so making sure to zoom out, which goes back to state before zooming action
             let prevSelected = this.itemIndex;
-            let didZoom = docAtCurrent.zoomButton;
-            // for (; !didZoom && prevSelected > 0 && this.childDocs[prevSelected].groupButton; prevSelected--) {
-            //     didZoom = this.childDocs[prevSelected].zoomButton;
-            // }
             prevSelected = Math.max(0, prevSelected - 1);
-
             this.gotoDocument(prevSelected, this.itemIndex);
         }
     }
@@ -159,19 +165,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                 const panelWidth: number = srcDocView.props.PanelWidth();
                 const panelHeight: number = srcDocView.props.PanelHeight();
                 console.log("srcDocView: " + srcDocView.props.PanelWidth());
-                // console.log("layoutdoc._width: " + layoutdoc._width);
-                // console.log("srcContext._width: " + srcContext._width);
                 const newPanX = NumCast(presTargetDoc.x) + NumCast(layoutdoc._width) / 2;
                 const newPanY = NumCast(presTargetDoc.y) + NumCast(layoutdoc._height) / 2;
-                // const newPanX = NumCast(presTargetDoc.x) + panelWidth / 2;
-                // const newPanY = NumCast(presTargetDoc.y) + panelHeight / 2;
                 let newScale = 0.9 * Math.min(Number(panelWidth) / vfWidth, Number(panelHeight) / vfHeight);
-                // srcContext._panX = newPanX + (NumCast(presTargetDoc._viewScale) * this.checkList(presTargetDoc, presTargetDoc["viewfinder-left-indexed"]) + NumCast(presTargetDoc._panX) + (this.checkList(presTargetDoc, presTargetDoc["viewfinder-width-indexed"]) / 2));
-                // srcContext._panY = newPanY + (NumCast(presTargetDoc._viewScale) * this.checkList(presTargetDoc, presTargetDoc["viewfinder-top-indexed"]) + NumCast(presTargetDoc._panY) + (this.checkList(presTargetDoc, presTargetDoc["viewfinder-height-indexed"]) / 2));
                 srcContext._panX = newPanX + (vfLeft + (vfWidth / 2));
                 srcContext._panY = newPanY + (vfTop + (vfHeight / 2));
-                // srcContext._panX = newPanX
-                // srcContext._panY = newPanY
                 srcContext._viewScale = newScale;
                 console.log("X: " + srcContext._panX + ", Y: " + srcContext._panY + ", Scale: " + srcContext._viewScale);
             }
@@ -203,9 +201,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
             const tagDoc = Cast(curDoc.presentationTargetDoc, Doc, null);
             if (tagDoc) tagDoc.opacity = 1;
             if (curDoc.presHideTillShownButton) {
-                console.log("-------------hide before---------------");
-                console.log("this.itemIndex: " + this.itemIndex);
-                console.log("index: " + index)
                 if (index > this.itemIndex) {
                     tagDoc.opacity = 0;
                 } else if (!curDoc.presHideAfterButton) {
@@ -213,9 +208,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                 }
             }
             if (curDoc.presHideAfterButton) {
-                console.log("-------------hide after---------------");
-                console.log("this.itemIndex: " + (this.itemIndex + 1));
-                console.log("index: " + (index + 1))
                 if (index < this.itemIndex) {
                     tagDoc.opacity = 0;
                 } else if (!curDoc.presHideTillShownButton) {
@@ -225,73 +217,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         });
     }
 
-    @action
-    onHideAfterPresClick = () => {
-        this.childDocs.forEach((doc, index) => {
-            const curDoc = Cast(doc, Doc, null);
-            const tagDoc = Cast(curDoc.presentationTargetDoc, Doc, null);
-            if (curDoc.presHideAfterButton) {
-                if (index < this.itemIndex) {
-                    tagDoc.opacity = 0;
-                } else if (index = this.itemIndex) {
-                    tagDoc.opacity = 1;
-                }
-            }
-        });
-    }
-
-    /**
-     * This is the method that checks for the actions that need to be performed
-     * before the document has been presented, which involves 3 button options:
-     * Hide Until Presented, Hide After Presented, Fade After Presented
-     */
-    // @action
-    // hideDocumentInPres = () => {
-    //     this.updateCurrentPresentation();
-    //     this.childDocs.forEach((doc, i) => {
-    //         const tagDoc = Cast(doc.presentationTargetDoc, Doc, null);
-    //         console.log("HB: " + doc.presHideTillShownButton);
-    //         console.log("HA: " + doc.presHideAfterButton);
-    //         if (doc.presHideTillShownButton) {
-    //             if (i < this.itemIndex) {
-    //                 console.log(i + 1 + "hide before");
-    //                 tagDoc.opacity = 0;
-    //                 console.log(tagDoc.opacity);
-    //             } else {
-    //                 tagDoc.opacity = 1;
-    //             }
-    //         }
-    //         if (doc.presHideAfterButton) {
-    //             if (i > this.itemIndex) {
-    //                 console.log(i + 1 + "hide after");
-    //                 tagDoc.opacity = 0;
-    //                 console.log(tagDoc.opacity);
-    //             } else {
-    //                 tagDoc.opacity = 1;
-    //             }
-    //         }
-    //     });
-    // }
-
-    /**
-     * This is the method that checks for the actions that need to be performed
-     * after the document has been presented, which involves 3 button options:
-     * Hide Until Presented, Hide After Presented, Fade After Presented
-     */
-    // showAfterPresented = (index: number) => {
-    //     this.updateCurrentPresentation();
-    //     this.childDocs.forEach((doc, ind) => {
-    //         const presTargetDoc = doc.presentationTargetDoc as Doc;
-    //         //the order of cases is aligned based on priority
-    //         if (doc.presHideTillShownButton && ind <= index) {
-    //             presTargetDoc.opacity = 1;
-    //         }
-    //         if (doc.presHideAfterButton && ind < index) {
-    //             presTargetDoc.opacity = 0;
-    //         }
-    //     });
-    // }
-
     /**
      * This method makes sure that cursor navigates to the element that
      * has the option open and last in the group. If not in the group, and it has
@@ -310,24 +235,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                 if (srcContext) this.layoutDoc.presCollection = srcContext;
             } else if (targetDoc) this.layoutDoc.presCollection = targetDoc;
         }
-        if (srcContext) console.log("NC: " + srcContext.title);
-        if (presCollection) console.log("PC: " + presCollection.title);
         if (collectionDocView) {
-            if (activeItem.openDocument) {
-                collectionDocView.props.addDocTab(activeItem, "inPlace");
-            } else if (srcContext && srcContext !== presCollection) {
-                if (activeItem.openDocument) {
-                    collectionDocView.props.addDocTab(activeItem, "inPlace");
-                } else {
-                    console.log("Case 1: new srcContext inside of current collection so add a new tab to the current pres collection");
-                    console.log(collectionDocView);
-                    collectionDocView.props.addDocTab(srcContext, "inPlace");
-                }
+            if (srcContext && srcContext !== presCollection) {
+                // Case 1: new srcContext inside of current collection so add a new tab to the current pres collection
+                collectionDocView.props.addDocTab(srcContext, "inPlace");
             }
         }
-        if (targetDoc.presWebsiteData) {
-            targetDoc.data = targetDoc.presWebsiteData;
-        }
         // else if (srcContext) {
         //     console.log("Case 2: srcContext - not open and collection containing this document exists, so open collection that contains it and then await zooming in on document");
         //     this.props.addDocTab(srcContext, "onRight");
@@ -354,6 +267,17 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
             //awaiting jump so that new scale can be found, since jumping is async
             targetDoc && await DocumentManager.Instance.jumpToDocument(targetDoc, willZoom, undefined, srcContext);
         }
+        if (activeItem.presPinView) {
+            targetDoc._panX = activeItem.presPinViewX;
+            targetDoc._panY = activeItem.presPinViewY;
+            targetDoc._viewScale = activeItem.presPinViewScale;
+        }
+        if (collectionDocView && activeItem.openDocument) {
+            collectionDocView.props.addDocTab(activeItem, "inPlace");
+        }
+        if (targetDoc.presWebsiteData) {
+            targetDoc.data = targetDoc.presWebsiteData;
+        }
     }
 
     //The function that is called when a document is clicked or reached through next or back.
@@ -381,6 +305,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
     @observable _presTimer!: NodeJS.Timeout;
 
     //The function that starts or resets presentaton functionally, depending on status flag.
+    @undoBatch
     @action
     startOrResetPres = (startSlide: number) => {
         this.updateCurrentPresentation();
@@ -432,31 +357,15 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         this.turnOffEdit();
         if (srcContext) {
             if (srcContext.miniPres) {
-                document.removeEventListener("keydown", this.keyEvents, false);
+                document.removeEventListener("keydown", this.minimizeEvents, false);
                 srcContext.miniPres = false;
-                // Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocuments as Doc), undefined, this.rootDoc);
                 CollectionDockingView.AddRightSplit(this.rootDoc);
-                // this.layoutDoc.inOverlay = false;
             } else {
-                document.addEventListener("keydown", this.keyEvents, false);
+                document.addEventListener("keydown", this.minimizeEvents, false);
                 srcContext.miniPres = true;
                 this.props.addDocTab?.(this.rootDoc, "close");
-                // Doc.AddDocToList((Doc.UserDoc().myOverlayDocuments as Doc), undefined, this.rootDoc);
             }
         }
-        // if (srcContext) {
-        //     Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocuments as Doc), undefined, this.rootDoc);
-        //     CollectionDockingView.AddRightSplit(this.rootDoc);
-        //     this.layoutDoc.inOverlay = false;
-        // }
-        // else {
-        //         const pt = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
-        //         this.rootDoc.x = pt[0];// 500;//e.clientX + 25;
-        //         this.rootDoc.y = pt[1];////e.clientY - 25;
-        //         this.props.addDocTab?.(this.rootDoc, "close");
-        //         Doc.AddDocToList((Doc.UserDoc().myOverlayDocuments as Doc), undefined, this.rootDoc);
-        //     }
-        // }
     }
 
     @undoBatch
@@ -464,7 +373,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         //@ts-ignore
         const viewType = e.target.selectedOptions[0].value as CollectionViewType;
         viewType === CollectionViewType.Stacking && (this.rootDoc._pivotField = undefined); // pivot field may be set by the user in timeline view (or some other way) -- need to reset it here
-        // this.updateMinimize(this.rootDoc._viewType = viewType);
+        this.rootDoc._viewType = viewType;
         if (viewType === CollectionViewType.Stacking) this.layoutDoc._gridGap = 5;
     });
 
@@ -485,7 +394,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         } else if (movement === 'switch') {
             targetDoc.presTransition = 0;
             activeItem.presSwitchButton = !activeItem.presSwitchButton;
-            if (activeItem.presSwitchButton) activeItem.presMovement = 'Switch';
+            if (activeItem.presSwitchButton) activeItem.presMovement = 'Jump cut';
             else activeItem.presMovement = 'None';
         } else {
             activeItem.presMovement = 'None';
@@ -496,12 +405,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
     });
 
     whenActiveChanged = action((isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive));
+    // For dragging documents into the presentation trail
     addDocumentFilter = (doc: Doc | Doc[]) => {
         const docs = doc instanceof Doc ? [doc] : doc;
         docs.forEach((doc, i) => {
             if (this.childDocs.includes(doc)) {
-                console.log(docs.length);
-                console.log(i + 1);
                 if (docs.length === i + 1) return false;
             } else {
                 doc.aliasOf instanceof Doc && (doc.presentationTargetDoc = doc.aliasOf);
@@ -574,33 +482,45 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         }
     }
 
+    @action
+    minimizeEvents = (e: KeyboardEvent) => {
+        e.stopPropagation();
+        e.preventDefault();
+        if (e.keyCode === 27) { // Escape key
+            this.layoutDoc.presStatus = "edit";
+        } if (e.keyCode === 37) { // left(37) / a(65) / up(38) to go back
+            this.back();
+        } if (e.keyCode === 39) { // right (39) / d(68) / down(40) to go to next
+            this.next();
+        }
+    }
+
     //Esc click
     @action
     keyEvents = (e: KeyboardEvent) => {
         e.stopPropagation();
         e.preventDefault();
-        // switch(e.keyCode) {
-        //     case 27: console.log("escape");
-        //     case 65 && (e.metaKey || e.altKey):
-        // }
-        // Escape key
-        if (e.keyCode === 27) {
+
+        if (e.keyCode === 27) { // Escape key
             if (this.layoutDoc.presStatus === "edit") this._selectedArray = [];
             else this.layoutDoc.presStatus = "edit";
-            // Ctrl-A to select all
-        } if ((e.metaKey || e.altKey) && e.keyCode === 65) {
+        } if ((e.metaKey || e.altKey) && e.keyCode === 65) { // Ctrl-A to select all
             if (this.layoutDoc.presStatus === "edit") this._selectedArray = this.childDocs;
-            // left(37) / a(65) / up(38) to go back
-        } if (e.keyCode === 37) {
+        } if (e.keyCode === 37) { // left(37) / a(65) / up(38) to go back
             if (this.layoutDoc.presStatus !== "edit") this.back();
-            // right (39) / d(68) / down(40) to go to next
-        } if (e.keyCode === 39) {
-            if (this.layoutDoc.presStatus !== "edit") this.next();
-            // spacebar to 'present' or go to next slide
-        } if (e.keyCode === 32) {
+        } if (e.keyCode === 39) { // right (39) / d(68) / down(40) to go to next
             if (this.layoutDoc.presStatus !== "edit") this.next();
+        } if (e.keyCode === 32) { // spacebar to 'present' or autoplay
+            if (this.layoutDoc.presStatus !== "edit") this.startOrResetPres(0);
             else this.layoutDoc.presStatus = "manual";
         }
+        if (e.keyCode === 8) { // delete selected items
+            if (this.layoutDoc.presStatus === "edit") {
+                this._selectedArray.forEach((doc, i) => {
+                    this.removeDocument(doc);
+                });
+            }
+        }
     }
 
     @observable private transitionTools: boolean = false;
@@ -617,7 +537,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
     viewPaths = async () => {
         const srcContext = Cast(this.rootDoc.presCollection, Doc, null);
         if (this.pathBoolean) {
-            console.log("true");
             if (srcContext) {
                 this.togglePath();
                 srcContext._fitToBox = false;
@@ -625,7 +544,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                 srcContext.presPathView = false;
             }
         } else {
-            console.log("false");
             if (srcContext) {
                 this.togglePath();
                 srcContext._fitToBox = true;
@@ -633,13 +551,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                 srcContext.presPathView = true;
             }
         }
-        console.log("view paths");
         const viewType = srcContext?._viewType;
         const fit = srcContext?._fitToBox;
-
-        // if (!DocumentManager.Instance.getDocumentView(curPres)) {
-        //     CollectionDockingView.AddRightSplit(curPres);
-        // }
     }
 
     @computed get order() {
@@ -664,7 +577,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
 
     @computed get paths() {
         let pathPoints = "";
-        console.log(this.childDocs.length - 1);
         this.childDocs.forEach((doc, index) => {
             const targetDoc = Cast(doc.presentationTargetDoc, Doc, null);
             const srcContext = Cast(targetDoc.context, Doc, null);
@@ -678,7 +590,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                 else pathPoints = pathPoints + " " + 0 + "," + 0;
             }
         });
-        console.log(pathPoints);
         return (<polyline
             points={pathPoints}
             style={{
@@ -720,12 +631,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         }
     }
 
+    // WHAT IS THIS?
     @action
     dropdownToggle = (menu: string) => {
-        console.log('presBox' + menu + 'Dropdown');
         const dropMenu = document.getElementById('presBox' + menu + 'Dropdown');
-        console.log(dropMenu);
-        console.log(dropMenu?.style.display);
         if (dropMenu) dropMenu.style.display === 'none' ? dropMenu.style.display = 'block' : dropMenu.style.display = 'none';
     }
 
@@ -749,8 +658,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         if (activeItem && targetDoc) {
             const transitionSpeed = targetDoc.presTransition ? String(Number(targetDoc.presTransition) / 1000) : 0.5;
             const duration = targetDoc.presDuration ? String(Number(targetDoc.presDuration) / 1000) : 2;
-            const transitionThumbLocation = String(-9.48 * Number(transitionSpeed) + 93);
-            const durationThumbLocation = String(9.48 * Number(duration));
             const effect = targetDoc.presEffect ? targetDoc.presEffect : 'None';
             activeItem.presMovement = activeItem.presMovement ? activeItem.presMovement : 'Zoom';
             return (
@@ -767,7 +674,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                                 <div className={`presBox-dropdownOption ${activeItem.presMovement === 'None' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('none')}>None</div>
                                 <div className={`presBox-dropdownOption ${activeItem.presMovement === 'Zoom' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('zoom')}>Pan and Zoom</div>
                                 <div className={`presBox-dropdownOption ${activeItem.presMovement === 'Pan' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('nav')}>Pan</div>
-                                <div className={`presBox-dropdownOption ${activeItem.presMovement === 'Switch' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('switch')}>Switch</div>
+                                <div className={`presBox-dropdownOption ${activeItem.presMovement === 'Jump cut' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('switch')}>Jump cut</div>
                             </div>
                         </div>
                         <div className="ribbon-doubleButton" style={{ display: activeItem.presMovement === 'Pan' || activeItem.presMovement === 'Zoom' ? "inline-flex" : "none" }}>
@@ -985,7 +892,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
     }
 
     createNewSlide = (layout?: string, title?: string, freeform?: boolean) => {
-        console.log("whats going on?");
         let doc = undefined;
         if (layout) doc = this.createTemplate(layout);
         if (freeform && layout) doc = this.createTemplate(layout, title);
@@ -1019,7 +925,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         const content2 = Docs.Create.TextDocument("Click to change text", { title: "Column 2", _width: 185, _height: 140, x: 205, y: 80, _fontSize: "14pt" });
         switch (layout) {
             case 'blank':
-                doc = Docs.Create.FreeformDocument([], { title: input ? input : "Blank slide", _width: 400, _height: 225, _fitToBox: true, x: x, y: y });
+                doc = Docs.Create.FreeformDocument([], { title: input ? input : "Blank slide", _width: 400, _height: 225, x: x, y: y });
                 break;
             case 'title':
                 doc = Docs.Create.FreeformDocument([title, subtitle], { title: input ? input : "Title slide", _width: 400, _height: 225, _fitToBox: true, x: x, y: y });
@@ -1084,14 +990,14 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
             CollectionFreeFormDocumentView.setupScroll(tagDoc, 0);
             CollectionFreeFormDocumentView.setupKeyframes(childDocs, 0);
         }
-        let lastFrame: number = 0;
-        childDocs.forEach((doc) => {
-            if (NumCast(doc.appearFrame) > lastFrame) lastFrame = NumCast(doc.appearFrame);
-        });
+        // let lastFrame: number = 0;
+        // childDocs.forEach((doc) => {
+        //     if (NumCast(doc.appearFrame) > lastFrame) lastFrame = NumCast(doc.appearFrame);
+        // });
         CollectionFreeFormDocumentView.updateScrollframe(tagDoc, currentFrame);
         CollectionFreeFormDocumentView.updateKeyframe(childDocs, currentFrame || 0);
         tagDoc.currentFrame = Math.max(0, (currentFrame || 0) + 1);
-        tagDoc.lastFrame = Math.max(NumCast(tagDoc.currentFrame), lastFrame);
+        tagDoc.lastFrame = Math.max(NumCast(tagDoc.currentFrame), NumCast(tagDoc.lastFrame));
         if (tagDoc.zoomProgressivize) {
             const resize = document.getElementById('resizable');
             if (resize) {
@@ -1153,20 +1059,20 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                     <div className={`presBox-ribbon ${this.progressivizeTools && this.layoutDoc.presStatus === "edit" ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
                         <div className="ribbon-box">
                             {this.stringType} selected
-                            <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.COL ? "inline-flex" : "none" }}>
+                            <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.COL && targetDoc._viewType === 'freeform' ? "inline-flex" : "none" }}>
                                 <div className="ribbon-button" style={{ backgroundColor: activeItem.presProgressivize ? "#aedef8" : "" }} onClick={this.progressivizeChild}>Child documents</div>
                                 <div className="ribbon-button" style={{ display: activeItem.presProgressivize ? "flex" : "none", backgroundColor: targetDoc.editProgressivize ? "#aedef8" : "" }} onClick={this.editProgressivize}>Edit</div>
                             </div>
-                            <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.COL || targetDoc.type === DocumentType.IMG ? "inline-flex" : "none" }}>
+                            <div className="ribbon-doubleButton" style={{ display: (targetDoc.type === DocumentType.COL && targetDoc._viewType === 'freeform') || targetDoc.type === DocumentType.IMG ? "inline-flex" : "none" }}>
                                 <div className="ribbon-button" style={{ backgroundColor: activeItem.zoomProgressivize ? "#aedef8" : "" }} onClick={this.progressivizeZoom}>Internal zoom</div>
                                 <div className="ribbon-button" style={{ display: activeItem.zoomProgressivize ? "flex" : "none", backgroundColor: targetDoc.editZoomProgressivize ? "#aedef8" : "" }} onClick={this.editZoomProgressivize}>Viewfinder</div>
                                 {/* <div className="ribbon-button" style={{ display: activeItem.zoomProgressivize ? "flex" : "none", backgroundColor: targetDoc.editSnapZoomProgressivize ? "#aedef8" : "" }} onClick={this.editSnapZoomProgressivize}>Snapshot</div> */}
                             </div>
-                            <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.RTF ? "inline-flex" : "none" }}>
+                            <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.COL && targetDoc._viewType === 'freeform' ? "inline-flex" : "none" }}>
                                 <div className="ribbon-button" onClick={this.progressivizeText}>Text progressivize</div>
                                 <div className="ribbon-button" style={{ display: activeItem.textProgressivize ? "flex" : "none", backgroundColor: targetDoc.editTextProgressivize ? "#aedef8" : "" }} onClick={this.editTextProgressivize}>Edit</div>
                             </div>
-                            <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.PDF ? "inline-flex" : "none" }}>
+                            <div className="ribbon-doubleButton" style={{ display: targetDoc._viewType === "stacking" || targetDoc.type === DocumentType.PDF || targetDoc.type === DocumentType.WEB || targetDoc.type === DocumentType.RTF ? "inline-flex" : "none" }}>
                                 <div className="ribbon-button" style={{ backgroundColor: activeItem.scrollProgressivize ? "#aedef8" : "" }} onClick={this.progressivizeScroll}>Scroll progressivize</div>
                                 <div className="ribbon-button" style={{ display: activeItem.scrollProgressivize ? "flex" : "none", backgroundColor: targetDoc.editScrollProgressivize ? "#aedef8" : "" }} onClick={this.editScrollProgressivize}>Edit</div>
                             </div>
@@ -1188,7 +1094,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                                 </div>
                                 <Tooltip title={<><div className="dash-tooltip">{"Last frame"}</div></>}><div className="ribbon-property">{NumCast(targetDoc.lastFrame)}</div></Tooltip>
                             </div>
-                            <div className="ribbon-button" style={{ height: 20, backgroundColor: "#5a9edd" }} onClick={() => console.log("play frames")}>Play</div>
+                            <div className="ribbon-button" style={{ height: 20, backgroundColor: "#5a9edd" }} onClick={() => console.log(" TODO: play frames")}>Play</div>
                         </div>
                     </div>
                 </div>
@@ -1298,9 +1204,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null);
         const docs = DocListCast(targetDoc[Doc.LayoutFieldKey(targetDoc)]);
         targetDoc.presProgressivize = !targetDoc.presProgressivize;
-        console.log(targetDoc.presProgressivize);
         if (activeItem.presProgressivize) {
-            console.log("progressivize");
             targetDoc.currentFrame = 0;
             CollectionFreeFormDocumentView.setupKeyframes(docs, docs.length, true);
             targetDoc.lastFrame = docs.length - 1;
@@ -1350,9 +1254,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         const y: List<number> = ylist;
         const tags: JSX.Element[] = [];
         let pathPoints = ""; //List of all of the pathpoints that need to be added
-        // console.log(x);
-        // console.log(x.length);
-        // console.log(x[0]);
         for (let i = 0; i < x.length - 1; i++) {
             if (y[i] || x[i]) {
                 if (i === 0) pathPoints = (x[i] - 11) + "," + (y[i] + 33);
@@ -1630,7 +1531,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
     @undoBatch
     @action
     nextAppearFrame = (doc: Doc, i: number): void => {
-        console.log("next");
         const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
         const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null);
         const appearFrame = Cast(doc.appearFrame, "number", null);
@@ -1638,9 +1538,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
             doc.appearFrame = 0;
         }
         doc.appearFrame = appearFrame + 1;
-        const olist = new List<number>(numberRange(NumCast(targetDoc.lastFrame)).map(t => targetDoc.presProgressivize && t < (doc.appearFrame ? doc.appearFrame : i) ? 0 : 1));
-        doc["opacity-indexed"] = olist;
-        console.log(doc.appearFrame);
+        this.updateOpacityList(doc["opacity-indexed"], NumCast(doc.appearFrame));
     }
 
     @undoBatch
@@ -1654,9 +1552,32 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
             doc.appearFrame = 0;
         }
         doc.appearFrame = Math.max(0, appearFrame - 1);
-        const olist = new List<number>(numberRange(NumCast(targetDoc.lastFrame)).map(t => targetDoc.presProgressivize && t < (doc.appearFrame ? doc.appearFrame : i) ? 0 : 1));
-        doc["opacity-indexed"] = olist;
-        console.log(doc.appearFrame);
+        this.updateOpacityList(doc["opacity-indexed"], NumCast(doc.appearFrame));
+    }
+
+    @action
+    updateOpacityList = (list: any, frame: number) => {
+        const x: List<number> = list;
+        if (x && x.length >= frame) {
+            for (let i = 0; i < x.length; i++) {
+                if (i < frame) {
+                    x[i] = 0;
+                } else if (i >= frame) {
+                    x[i] = 1;
+                }
+            }
+            list = x;
+        } else {
+            x.length = frame + 1;
+            for (let i = 0; i < x.length; i++) {
+                if (i < frame) {
+                    x[i] = 0;
+                } else if (i >= frame) {
+                    x[i] = 1;
+                }
+            }
+            list = x;
+        }
     }
 
     @computed get moreInfoDropdown() {
@@ -1746,37 +1667,37 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                     onPointerDown={e => e.stopPropagation()}
                     onChange={this.viewChanged}
                     value={mode}>
-                    {/* <option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Invalid}>Min</option> */}
                     <option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Stacking}>List</option>
-                    {/* <option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Time}>Time</option> */}
                     <option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Carousel}>Slides</option>
                 </select>
                 <div className="presBox-presentPanel">
-                    <span className={`presBox-button ${this.layoutDoc.presStatus !== "edit" ? "active" : ""}`} title={"Reset Presentation" + this.layoutDoc.presStatus ? "" : " From Start"} style={{ minWidth: 60, gridColumn: 2 }}>
-                        <div className="presBox-button-left" onClick={() => this.startOrResetPres(0)}>
-                            <FontAwesomeIcon icon={"clock"} /> &nbsp;
-                            <FontAwesomeIcon icon={this.layoutDoc.presStatus === "auto" ? "pause" : "play"} />
-                        </div>
-                        <div className={`presBox-button-right ${this.playTools ? "active" : ""}`} onClick={e => { e.stopPropagation; this.togglePlay(); }}>
-                            <FontAwesomeIcon className="dropdown" style={{ margin: 0, transform: this.playTools ? 'rotate(180deg)' : 'rotate(0deg)' }} icon={"angle-down"} />
-                            {this.playDropdown}
-                        </div>
-                    </span>
-                    <span className={`presBox-button ${this.layoutDoc.presStatus === "edit" ? "present" : ""}`} title="Present">
+                    <span className={`presBox-button ${this.layoutDoc.presStatus === "edit" ? "present" : ""}`}>
                         <div className="presBox-button-left" onClick={() => this.layoutDoc.presStatus = "manual"}><FontAwesomeIcon icon={"play-circle"} /> &nbsp; Present </div>
                         <div className={`presBox-button-right ${this.presentTools ? "active" : ""}`} onClick={e => { e.stopPropagation; this.togglePresent(); }}>
                             <FontAwesomeIcon className="dropdown" style={{ margin: 0, transform: this.presentTools ? 'rotate(180deg)' : 'rotate(0deg)' }} icon={"angle-down"} />
                             {this.presentDropdown}
                         </div>
                     </span>
-                    <div className={`presBox-button ${this.layoutDoc.presStatus !== "edit" ? "active" : ""}`} title="Back" onClick={this.back}>
-                        <FontAwesomeIcon icon={"arrow-left"} />
-                    </div>
-                    <div className={`presBox-button ${this.layoutDoc.presStatus !== "edit" ? "active" : ""}`} title="Next" onClick={this.next}>
-                        <FontAwesomeIcon icon={"arrow-right"} />
-                    </div>
-                    <div className={`presBox-button ${this.layoutDoc.presStatus !== "edit" ? "edit" : ""}`} title="Next" onClick={() => this.layoutDoc.presStatus = "edit"}>
-                        <FontAwesomeIcon icon={"times"} />
+                    <div className="miniPresOverlay" style={{ display: this.layoutDoc.presStatus !== "edit" ? "inline-flex" : "none" }}>
+                        {/* <span className={`presBox-button ${this.layoutDoc.presStatus !== "edit" ? "active" : ""}`}>
+                            <div className="presBox-button-left" onClick={() => this.startOrResetPres(0)}>
+                                <FontAwesomeIcon icon={"clock"} /> &nbsp;
+                                <FontAwesomeIcon icon={this.layoutDoc.presStatus === "auto" ? "pause" : "play"} />
+                            </div>
+                            <div className={`presBox-button-right ${this.playTools ? "active" : ""}`} onClick={e => { e.stopPropagation; this.togglePlay(); }}>
+                                <FontAwesomeIcon className="dropdown" style={{ margin: 0, transform: this.playTools ? 'rotate(180deg)' : 'rotate(0deg)' }} icon={"angle-down"} />
+                                {this.playDropdown}
+                            </div>
+                        </span> */}
+                        <div className="miniPres-button" onClick={this.back}><FontAwesomeIcon icon={"arrow-left"} /></div>
+                        <div className="miniPres-button" onClick={() => this.startOrResetPres(this.itemIndex)}><FontAwesomeIcon icon={PresBox.Instance.layoutDoc.presStatus === "auto" ? "pause" : "play"} /></div>
+                        <div className="miniPres-button" onClick={this.next}><FontAwesomeIcon icon={"arrow-right"} /></div>
+                        <div className="miniPres-divider"></div>
+                        <div className="miniPres-button-text">Slide {this.itemIndex + 1} / {this.childDocs.length}</div>
+                        <div className="miniPres-divider"></div>
+                        <div className="miniPres-button" onClick={() => this.layoutDoc.presStatus = "edit"}>
+                            <FontAwesomeIcon icon={"times"} />
+                        </div>
                     </div>
                 </div>
             </div>
@@ -1809,14 +1730,4 @@ Scripting.addGlobal(function lookupPresBoxField(container: Doc, field: string, d
     if (field === '_itemIndex') return container._itemIndex;
     if (field === 'presBox') return container;
     return undefined;
-});
-
-
-
-// console.log("render = " + this.layoutDoc.title + " " + this.layoutDoc.presStatus);
-// const presOrderedDocs = DocListCast(activeItem.presOrderedDocs);
-// if (presOrderedDocs.length != this.childDocs.length || presOrderedDocs.some((pd, i) => pd !== this.childDocs[i])) {
-//     this.rootDoc.presOrderedDocs = new List<Doc>(this.childDocs.slice());
-// }
-
-
+});
\ No newline at end of file
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index fc65f34eb..76d23ddfe 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -536,6 +536,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                 Doc.AddDocToList(Cast(Doc.UserDoc()["template-notes"], Doc, null), "data", this.rootDoc);
             }, icon: "eye"
         });
+        appearanceItems.push({ description: "Create progressivized slide...", event: this.progressivizeText, icon: "desktop" });
         cm.addItem({ description: "Appearance...", subitems: appearanceItems, icon: "eye" });
 
         const options = cm.findByDescription("Options...");
@@ -547,6 +548,69 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         this._downX = this._downY = Number.NaN;
     }
 
+    progressivizeText = () => {
+        const list = this.ProseRef?.getElementsByTagName("li");
+        const mainBulletText: string[] = [];
+        const mainBulletList: Doc[] = [];
+        if (list) {
+            const newBullets: Doc[] = this.recursiveProgressivize(1, list);
+            mainBulletList.push.apply(mainBulletList, newBullets);
+        }
+        console.log(mainBulletList.length);
+        const title = Docs.Create.TextDocument(StrCast(this.rootDoc.title), { title: "Title", _width: 800, _height: 70, x: 20, y: -10, _fontSize: '20pt', backgroundColor: "rgba(0,0,0,0)", appearFrame: 0, _fontWeight: 700 });
+        mainBulletList.push(title);
+        const doc = Docs.Create.FreeformDocument(mainBulletList, {
+            title: StrCast(this.rootDoc.title),
+            x: NumCast(this.props.Document.x), y: NumCast(this.props.Document.y) + NumCast(this.props.Document._height) + 10,
+            _width: 400, _height: 225, _fitToBox: true,
+        });
+        this.props.addDocument?.(doc);
+    }
+
+    recursiveProgressivize = (nestDepth: number, list: HTMLCollectionOf<HTMLLIElement>, d?: number, y?: number, before?: string): Doc[] => {
+        const mainBulletList: Doc[] = [];
+        let b = d ? d : 0;
+        let yLoc = y ? y : 0;
+        let nestCount = 0;
+        let count: string = before ? before : '';
+        const fontSize: string = (16 - (nestDepth * 2)) + 'pt';
+        const xLoc: number = (nestDepth * 20);
+        const width: number = 390 - xLoc;
+        const height: number = 55 - (nestDepth * 5);
+        for (let i = 0; i < list.length; i++) {
+            const mainBullets: number = Number(list[i].getAttribute("data-bulletstyle"));
+            if (mainBullets === nestDepth) {
+                if (list[i].childElementCount > 1) {
+                    b++;
+                    nestCount++;
+                    count = before ? count + nestCount + "." : nestCount + ".";
+                    yLoc += height;
+                    const text = list[i].getElementsByTagName("p")[0].innerText;
+                    const length = text.length;
+                    console.log(yLoc);
+                    const bullet1 = Docs.Create.TextDocument(count + " " + text, { title: "Slide text", _width: width, _height: height, x: xLoc, y: 10 + (yLoc), _fontSize: fontSize, backgroundColor: "rgba(0,0,0,0)", appearFrame: d ? d : b });
+                    mainBulletList.push(bullet1);
+                    const newList = this.recursiveProgressivize(nestDepth + 1, list[i].getElementsByTagName("li"), b, yLoc, count);
+                    mainBulletList.push.apply(mainBulletList, newList);
+                    b += newList.length;
+                    yLoc += newList.length * (55 - ((nestDepth + 1) * 5));
+                } else {
+                    b++;
+                    nestCount++;
+                    count = before ? count + nestCount + "." : nestCount + ".";
+                    yLoc += height;
+                    const text = list[i].innerText;
+                    const length = text.length;
+                    console.log(yLoc);
+                    const bullet1 = Docs.Create.TextDocument(count + " " + text, { title: "Slide text", _width: width, _height: height, x: xLoc, y: 10 + (yLoc), _fontSize: fontSize, backgroundColor: "rgba(0,0,0,0)", appearFrame: d ? d : b });
+                    mainBulletList.push(bullet1);
+                }
+            }
+        }
+        console.log("b: " + b);
+        return mainBulletList;
+    }
+
     recordDictation = () => {
         DictationManager.Controls.listen({
             interimHandler: this.setCurrentBulletContent,
@@ -1374,6 +1438,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                         color: this.props.color ? this.props.color : StrCast(this.layoutDoc[this.props.fieldKey + "-color"], this.props.hideOnLeave ? "white" : "inherit"),
                         pointerEvents: interactive ? undefined : "none",
                         fontSize: Cast(this.layoutDoc._fontSize, "string", null),
+                        fontWeight: Cast(this.layoutDoc._fontWeight, "number", null),
                         fontFamily: StrCast(this.layoutDoc._fontFamily, "inherit"),
                         transition: "opacity 1s"
                     }}
diff --git a/src/client/views/presentationview/PresElementBox.scss b/src/client/views/presentationview/PresElementBox.scss
index 159cb5f8a..fa70b2a41 100644
--- a/src/client/views/presentationview/PresElementBox.scss
+++ b/src/client/views/presentationview/PresElementBox.scss
@@ -2,7 +2,8 @@
     display: grid;
     grid-template-columns: max-content max-content max-content;
     background-color: #d5dce2;
-    // box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.25);
+    font-family: Roboto;
+    letter-spacing: normal;
     position: relative;
     pointer-events: all;
     width: 100%;
@@ -21,13 +22,30 @@
 
     .presElementBox-highlight {
         position: absolute;
-        transform: translate(-100px, -6px);
+        transform: translate(-100px, -4px);
         z-index: -1;
         width: calc(100% + 200px);
-        height: calc(100% + 12px);
+        height: calc(100% + 8px);
         background-color: #AEDDF8;
     }
 
+    .presElementBox-highlightTop {
+        position: absolute;
+        transform: translate(-100px, -4px);
+        z-index: -1;
+        width: calc(100% + 200px);
+        height: calc(50% + 4px);
+    }
+
+    .presElementBox-highlightBottom {
+        position: absolute;
+        transform: translate(-100px, 0px);
+        z-index: -1;
+        top: 50%;
+        width: calc(100% + 200px);
+        height: calc(50% + 4px);
+    }
+
     .documentView-node {
         position: absolute;
         z-index: 1;
@@ -79,8 +97,12 @@
 
 .presElementBox-number {
     font-size: 12px;
+    width: 20;
     font-weight: 700;
-    left: -15;
+    text-align: right;
+    justify-content: center;
+    align-content: center;
+    left: -20;
     position: absolute;
     display: inline-block;
     overflow: hidden;
@@ -110,9 +132,8 @@
     font-size: 10;
     font-weight: 300;
     font-family: Roboto;
-    /* font-style: italic; */
+    z-index: 300;
     letter-spacing: normal;
-    /* left: 10px; */
 }
 
 .presElementBox-embedded {
@@ -174,7 +195,7 @@
     bottom: 3px;
     width: 20px;
     height: 20px;
-    z-index: 200;
+    z-index: 300;
     display: flex;
     background-color: black;
     color: white;
diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx
index b3d8cca98..e035ed0b8 100644
--- a/src/client/views/presentationview/PresElementBox.tsx
+++ b/src/client/views/presentationview/PresElementBox.tsx
@@ -220,7 +220,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
         let durationInS: number;
         if (this.targetDoc.presDuration) durationInS = NumCast(this.targetDoc.presDuration) / 1000;
         else durationInS = 2;
-        return "V: " + durationInS + "s";
+        return "D: " + durationInS + "s";
     }
 
     @computed get transition() {
@@ -245,25 +245,61 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
         }
     }
 
+    headerUp = (e: React.PointerEvent<HTMLDivElement>) => {
+        e.stopPropagation();
+        e.preventDefault();
+        DragManager.docsBeingDragged = [];
+        this._highlightTopRef.current!.style.borderBottom = "0px";
+        this._highlightBottomRef.current!.style.borderBottom = "0px";
+    }
+
     startDrag = (e: PointerEvent, down: number[], delta: number[]) => {
         // const ele: HTMLElement[] = PresBox.Instance._eleArray.map(doc => doc);
         const activeItem = this.rootDoc;
         const dragData = new DragManager.DocumentDragData(PresBox.Instance.sortArray().map(doc => doc));
         // let value = this.getValue(this._heading);
         // value = typeof value === "string" ? `"${value}"` : value;
+        let dragItem: HTMLElement[] = [];
+        PresBox.Instance._dragArray.map(ele => {
+            const drag = ele;
+            drag.style.backgroundColor = "#d5dce2";
+            drag.style.borderRadius = '5px';
+            dragItem.push(drag);
+        });
         if (activeItem) {
-            DragManager.StartDocumentDrag(PresBox.Instance._dragArray.map(ele => ele), dragData, e.clientX, e.clientY);
+            DragManager.StartDocumentDrag(dragItem.map(ele => ele), dragData, e.clientX, e.clientY);
             activeItem.dragging = true;
             return true;
         }
         return false;
     }
 
+    private _highlightTopRef: React.RefObject<HTMLDivElement> = React.createRef();
+    private _highlightBottomRef: React.RefObject<HTMLDivElement> = React.createRef();
 
 
+    onPointerTop = (e: React.PointerEvent<HTMLDivElement>) => {
+        if (DragManager.docsBeingDragged.length > 0) {
+            this._highlightTopRef.current!.style.borderTop = "solid 2px #5B9FDD";
+        }
+    }
+
+    onPointerBottom = (e: React.PointerEvent<HTMLDivElement>) => {
+        if (DragManager.docsBeingDragged.length > 0) {
+            this._highlightBottomRef.current!.style.borderBottom = "solid 2px #5B9FDD";
+        }
+    }
+
+    onPointerLeave = (e: React.PointerEvent<HTMLDivElement>) => {
+        if (DragManager.docsBeingDragged.length > 0) {
+            this._highlightBottomRef.current!.style.borderBottom = "0px";
+            this._highlightTopRef.current!.style.borderTop = "0px";
+        }
+    }
+
     render() {
         const treecontainer = this.props.ContainingCollectionDoc?._viewType === CollectionViewType.Tree;
-        const className = "presElementBox-item" + (this.itemIndex === this.indexInPres ? " presElementBox-active" : "");
+        const className = "presElementBox-item" + (PresBox.Instance._selectedArray.includes(this.rootDoc) ? " presElementBox-active" : "");
         const pbi = "presElementBox-interaction";
         return !(this.rootDoc instanceof Doc) || this.targetDoc instanceof Promise ? (null) : (
             <div className={className} key={this.props.Document[Id] + this.indexInPres}
@@ -288,6 +324,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
                     }
                 }}
                 onPointerDown={this.headerDown}
+                onPointerUp={this.headerUp}
             >
                 <>
                     <div className="presElementBox-number">
@@ -297,7 +334,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
                         {`${this.targetDoc?.title}`}
                     </div>
                     <Tooltip title={<><div className="dash-tooltip">{"Movement speed"}</div></>}><div className="presElementBox-time" style={{ display: PresBox.Instance.toolbarWidth > 300 ? "block" : "none" }}>{this.transition}</div></Tooltip>
-                    <Tooltip title={<><div className="dash-tooltip">{"Duration of visibility"}</div></>}><div className="presElementBox-time" style={{ display: PresBox.Instance.toolbarWidth > 300 ? "block" : "none" }}>{this.duration}</div></Tooltip>
+                    <Tooltip title={<><div className="dash-tooltip">{"Duration"}</div></>}><div className="presElementBox-time" style={{ display: PresBox.Instance.toolbarWidth > 300 ? "block" : "none" }}>{this.duration}</div></Tooltip>
                     <Tooltip title={<><div className="dash-tooltip">{"Remove from presentation"}</div></>}><div
                         className="presElementBox-closeIcon"
                         // onPointerDown={e => e.stopPropagation()}
@@ -311,7 +348,9 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
                         <FontAwesomeIcon icon={(this.rootDoc.presExpandInlineButton ? "angle-up" : "angle-down")} onPointerDown={e => e.stopPropagation()} />
                     </div></Tooltip>
                 </>
-                <div className="presElementBox-highlight" style={{ display: PresBox.Instance._selectedArray.includes(this.rootDoc) ? "block" : "none" }} />
+                <div ref={this._highlightTopRef} onPointerOver={this.onPointerTop} onPointerLeave={this.onPointerLeave} className="presElementBox-highlightTop" style={{ zIndex: 299, backgroundColor: "rgba(0,0,0,0)" }} />
+                <div ref={this._highlightBottomRef} onPointerOver={this.onPointerBottom} onPointerLeave={this.onPointerLeave} className="presElementBox-highlightBottom" style={{ zIndex: 299, backgroundColor: "rgba(0,0,0,0)" }} />
+                <div className="presElementBox-highlight" style={{ backgroundColor: PresBox.Instance._selectedArray.includes(this.rootDoc) ? "#AEDDF8" : "rgba(0,0,0,0)" }} />
                 <div className="presElementBox-buttons" style={{ display: this.rootDoc.presExpandInlineButton ? "grid" : "none" }}>
                     <button title="Zoom" className={pbi + (this.rootDoc.presZoomButton ? "-selected" : "")} onClick={this.onZoomDocumentClick}><FontAwesomeIcon icon={"search"} onPointerDown={e => e.stopPropagation()} /></button>
                     <button title="Navigate" className={pbi + (this.rootDoc.presNavButton ? "-selected" : "")} onClick={this.onNavigateDocumentClick}><FontAwesomeIcon icon={"location-arrow"} onPointerDown={e => e.stopPropagation()} /></button>
-- 
cgit v1.2.3-70-g09d2


From cc905d329c88d7bdf9b7324a4f02ab92906ba7c8 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 5 Aug 2020 22:20:49 -0400
Subject: cleanup of presentation code pre-merge.

---
 src/client/documents/Documents.ts                  |  4 --
 src/client/util/CurrentUserUtils.ts                |  8 ++--
 src/client/views/InkingStroke.tsx                  |  6 +--
 src/client/views/MainView.tsx                      |  2 +-
 .../CollectionStackingViewFieldColumn.tsx          |  3 +-
 .../views/collections/CollectionTreeView.tsx       |  1 -
 .../collectionFreeForm/PropertiesView.tsx          |  4 +-
 src/client/views/nodes/AudioBox.tsx                |  1 -
 .../views/nodes/CollectionFreeFormDocumentView.tsx | 11 +----
 src/client/views/nodes/DocumentLinksButton.tsx     |  2 +-
 src/client/views/nodes/PresBox.tsx                 | 49 ++++++++++------------
 .../views/nodes/formattedText/FormattedTextBox.tsx | 17 ++++----
 .../views/nodes/formattedText/RichTextMenu.tsx     |  3 +-
 .../views/presentationview/PresElementBox.tsx      |  2 +-
 14 files changed, 46 insertions(+), 67 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 57fcf3a00..959aeac41 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -801,10 +801,6 @@ export namespace Docs {
             return InstanceFromProto(Prototypes.get(DocumentType.FONTICON), undefined, { hideLinkButton: true, ...(options || {}) });
         }
 
-        export function MenuIconDocument(options?: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.MENUICON), undefined, { hideLinkButton: true, ...(options || {}) });
-        }
-
         export function PresElementBoxDocument(options?: DocumentOptions) {
             return InstanceFromProto(Prototypes.get(DocumentType.PRESELEMENT), undefined, { ...(options || {}) });
         }
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 8023df8b4..4e59434b5 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -546,7 +546,7 @@ export class CurrentUserUtils {
                     btn.color = "white";
                     btn._backgroundColor = "";
                 }));
-            })
+            });
         });
         return doc.menuStack as Doc;
     }
@@ -763,13 +763,13 @@ export class CurrentUserUtils {
     }
 
     static setupSidebarContainer(doc: Doc) {
-        if (doc["sidebar"] === undefined) {
+        if (doc.sidebar === undefined) {
             const sidebarContainer = new Doc();
             sidebarContainer._chromeStatus = "disabled";
             sidebarContainer.onClick = ScriptField.MakeScript("freezeSidebar()");
-            doc["sidebar"] = new PrefetchProxy(sidebarContainer);
+            doc.sidebar = new PrefetchProxy(sidebarContainer);
         }
-        return doc["sidebar"] as Doc;
+        return doc.sidebar as Doc;
     }
 
     // setup the list of sidebar mode buttons which determine what is displayed in the sidebar
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 6c5eda256..4a77728b6 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -115,9 +115,9 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
             StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "transparent"),
             "none", "none", "0", scaleX, scaleY, "", this.props.active() ? "visiblepainted" : "none", false, true);
 
-        var controlPoints: { X: number, Y: number, I: number }[] = [];
-        var handlePoints: { X: number, Y: number, I: number, dot1: number, dot2: number }[] = [];
-        var handleLine: { X1: number, Y1: number, X2: number, Y2: number, X3: number, Y3: number, dot1: number, dot2: number }[] = [];
+        const controlPoints: { X: number, Y: number, I: number }[] = [];
+        const handlePoints: { X: number, Y: number, I: number, dot1: number, dot2: number }[] = [];
+        const handleLine: { X1: number, Y1: number, X2: number, Y2: number, X3: number, Y3: number, dot1: number, dot2: number }[] = [];
         if (data.length >= 4) {
             for (var i = 0; i <= data.length - 4; i += 4) {
                 controlPoints.push({ X: data[i].X, Y: data[i].Y, I: i });
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 138ff226f..7f50dda72 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -80,7 +80,7 @@ export class MainView extends React.Component {
     @computed private get mainContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeWorkspace, Doc)) : CurrentUserUtils.GuestWorkspace; }
     @computed public get mainFreeform(): Opt<Doc> { return (docs => (docs && docs.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); }
 
-    @observable public sidebarContent: any = this.userDoc?.["sidebar"];
+    @observable public sidebarContent: any = this.userDoc?.sidebar;
     @observable public panelContent: string = "none";
     @observable public showProperties: boolean = false;
     public isPointerDown = false;
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 68c233a16..fbc4e1552 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -12,6 +12,7 @@ import { NumCast, StrCast, Cast } from "../../../fields/Types";
 import { ImageField } from "../../../fields/URLField";
 import { TraceMobx } from "../../../fields/util";
 import { Docs, DocUtils } from "../../documents/Documents";
+import { DocumentType } from "../../documents/DocumentTypes";
 import { DragManager } from "../../util/DragManager";
 import { Transform } from "../../util/Transform";
 import { undoBatch } from "../../util/UndoManager";
@@ -366,7 +367,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
                             {this.props.parent.children(this.props.docList, uniqueHeadings.length)}
                             {singleColumn ? (null) : this.props.parent.columnDragger}
                         </div>
-                        {(chromeStatus !== 'view-mode' && chromeStatus !== 'disabled' && type !== 'presentation') ?
+                        {(chromeStatus !== 'view-mode' && chromeStatus !== 'disabled' && type !== DocumentType.PRES) ?
                             <div key={`${heading}-add-document`} className="collectionStackingView-addDocumentButton"
                                 style={{ width: style.columnWidth / style.numGroupColumns }}>
                                 <EditableView {...newEditableViewProps} menuCallback={this.menuCallback} />
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 8ec855c7c..3c7471d7c 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -133,7 +133,6 @@ class TreeView extends React.Component<TreeViewProps> {
     }
 
     protected createTreeDropTarget = (ele: HTMLDivElement) => {
-        console.log("ele");
         this._treedropDisposer?.();
         ele && (this._treedropDisposer = DragManager.MakeDropTarget(ele, this.treeDrop.bind(this), undefined, this.preTreeDrop.bind(this)), this.doc);
     }
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 2b0a00498..dcbf8e989 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -552,7 +552,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     getField(key: string) {
         //if (this.selectedDoc) {
-        return Field.toString(this.selectedDoc[key] as Field);
+        return Field.toString(this?.[key] as Field);
         // } else {
         //     return undefined as Opt<string>;
         // }
@@ -698,7 +698,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 <input className="width-range" type="range"
                     defaultValue={Number(this.widthStk)} min={1} max={100}
                     onChange={(action((e) => this.widthStk = e.target.value))}
-                    onMouseDown={(e) => { this._widthUndo = UndoManager.StartBatch("width undo");; }}
+                    onMouseDown={(e) => { this._widthUndo = UndoManager.StartBatch("width undo"); }}
                     onMouseUp={(e) => { this._widthUndo?.end(); this._widthUndo = undefined; }}
                 />
             </div>
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index dba92faae..2396e6973 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -21,7 +21,6 @@ import { Docs, DocUtils } from "../../documents/Documents";
 import { ComputedField } from "../../../fields/ScriptField";
 import { Networking } from "../../Network";
 import { LinkAnchorBox } from "./LinkAnchorBox";
-import { signedCookie } from "cookie-parser";
 
 // testing testing 
 
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 35ed6c5a5..42a42ddf1 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -18,8 +18,6 @@ import { DocumentType } from "../../documents/DocumentTypes";
 import { Zoom, Fade, Flip, Rotate, Bounce, Roll, LightSpeed } from 'react-reveal';
 import { PresBox } from "./PresBox";
 import { InkingStroke } from "../InkingStroke";
-import { PDFViewer } from "../pdf/PDFViewer";
-import { PDFBox } from "./PDFBox";
 
 export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
     dataProvider?: (doc: Doc, replica: string) => { x: number, y: number, zIndex?: number, opacity?: number, highlight?: boolean, z: number, transition?: string } | undefined;
@@ -119,7 +117,6 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
     }
 
     public static updateScrollframe(doc: Doc, time: number) {
-        let _pdfViewer: PDFViewer | undefined;
         const timecode = Math.round(time);
         const scrollIndexed = Cast(doc['scroll-indexed'], listSpec("number"), null);
         scrollIndexed?.length <= timecode + 1 && scrollIndexed.push(undefined as any as number);
@@ -191,15 +188,11 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
             const wlist = new List<number>(numberRange(timecode + 1).map(i => undefined) as any as number[]);
             const hlist = new List<number>(numberRange(timecode + 1).map(i => undefined) as any as number[]);
             const olist = new List<number>(numberRange(timecode + 1).map(t => progressivize && t < (doc.appearFrame ? doc.appearFrame : i) ? 0 : 1));
-            let oarray: List<number>;
-            console.log(doc.title + "AF: " + doc.appearFrame);
-            console.log("timecode: " + timecode);
-            oarray = olist;
+            const oarray = olist;
             oarray.fill(0, 0, NumCast(doc.appearFrame) - 1);
             oarray.fill(1, NumCast(doc.appearFrame), timecode);
             // oarray.fill(0, 0, NumCast(doc.appearFrame) - 1);
-            // oarray.fill(1, NumCast(doc.appearFrame), timecode);
-            // console.log(oarray);
+            // oarray.fill(1, NumCast(doc.appearFrame), timecode);\
             wlist[curTimecode] = NumCast(doc._width);
             hlist[curTimecode] = NumCast(doc._height);
             xlist[curTimecode] = NumCast(doc.x);
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 4713ce447..025669b41 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -125,7 +125,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
         } else if (this.props.InMenu && !this.props.StartLink && DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View) {
             const linkDoc = DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag");
             // this notifies any of the subviews that a document is made so that they can make finer-grained hyperlinks ().  see note above in onLInkButtonMoved
-            DocumentLinksButton.StartLink!._link = this.props.View._link = linkDoc;
+            DocumentLinksButton.StartLink._link = this.props.View._link = linkDoc;
             setTimeout(action(() => DocumentLinksButton.StartLink!._link = this.props.View._link = undefined), 0);
             LinkManager.currentLink = linkDoc;
             if (linkDoc) {
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index 1caefdc57..ccf1fb8e3 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -129,7 +129,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                 const nextChildDocs = DocListCast(nextTagDoc[Doc.LayoutFieldKey(presTargetDoc)]);
                 nextChildDocs.forEach((doc, i) => {
                     doc.opacity = 1;
-                })
+                });
             }
             const nextSelected = this.itemIndex + 1;
             this.gotoDocument(nextSelected, this.itemIndex);
@@ -158,28 +158,24 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         const vfHeight: number = this.checkList(presTargetDoc, presTargetDoc["viewfinder-height-indexed"]);
         // Case 1: document that is not a Golden Layout tab
         if (srcContext) {
-            console.log("CASE 1");
             const srcDocView = DocumentManager.Instance.getDocumentView(srcContext);
             if (srcDocView) {
                 const layoutdoc = Doc.Layout(presTargetDoc);
                 const panelWidth: number = srcDocView.props.PanelWidth();
                 const panelHeight: number = srcDocView.props.PanelHeight();
-                console.log("srcDocView: " + srcDocView.props.PanelWidth());
                 const newPanX = NumCast(presTargetDoc.x) + NumCast(layoutdoc._width) / 2;
                 const newPanY = NumCast(presTargetDoc.y) + NumCast(layoutdoc._height) / 2;
-                let newScale = 0.9 * Math.min(Number(panelWidth) / vfWidth, Number(panelHeight) / vfHeight);
+                const newScale = 0.9 * Math.min(Number(panelWidth) / vfWidth, Number(panelHeight) / vfHeight);
                 srcContext._panX = newPanX + (vfLeft + (vfWidth / 2));
                 srcContext._panY = newPanY + (vfTop + (vfHeight / 2));
                 srcContext._viewScale = newScale;
-                console.log("X: " + srcContext._panX + ", Y: " + srcContext._panY + ", Scale: " + srcContext._viewScale);
             }
         }
         // Case 2: document is the containing collection
         if (docView && !srcContext) {
-            console.log("CASE 2");
             const panelWidth: number = docView.props.PanelWidth();
             const panelHeight: number = docView.props.PanelHeight();
-            let newScale = 0.9 * Math.min(Number(panelWidth) / vfWidth, Number(panelHeight) / vfHeight);
+            const newScale = 0.9 * Math.min(Number(panelWidth) / vfWidth, Number(panelHeight) / vfHeight);
             presTargetDoc._panX = vfLeft + (vfWidth / 2);
             presTargetDoc._panY = vfTop + (vfWidth / 2);
             presTargetDoc._viewScale = newScale;
@@ -791,7 +787,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                                 <div className="ribbon-button" style={{ display: "flex", backgroundColor: targetDoc.editProgressivize ? "#aedef8" : "" }} onClick={this.editProgressivize}>Start manually</div>
                             </div>
                             <div className="ribbon-doubleButton" style={{ display: "flex" }}>
-                                <div className="ribbon-button" style={{ backgroundColor: activeItem.openDocument ? "#aedef8" : "" }} onClick={() => { activeItem.openDocument = !activeItem.openDocument }}>Open document</div>
+                                <div className="ribbon-button" style={{ backgroundColor: activeItem.openDocument ? "#aedef8" : "" }} onClick={() => activeItem.openDocument = !activeItem.openDocument}>Open document</div>
                             </div>
                             <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.WEB ? "inline-flex" : "none" }}>
                                 <div className="ribbon-button" onClick={this.progressivizeText}>Store original website</div>
@@ -808,15 +804,15 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
             <div>
                 <div className={'presBox-toolbar-dropdown'} style={{ display: this.newDocumentTools && this.layoutDoc.presStatus === "edit" ? "inline-flex" : "none" }} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
                     <div className="layout-container" style={{ height: 'max-content' }}>
-                        <div className="layout" style={{ border: this.layout === 'blank' ? 'solid 2px #5b9ddd' : '' }} onClick={() => runInAction(() => { this.layout = 'blank'; this.createNewSlide(this.layout); })} />
-                        <div className="layout" style={{ border: this.layout === 'title' ? 'solid 2px #5b9ddd' : '' }} onClick={() => runInAction(() => { this.layout = 'title'; this.createNewSlide(this.layout); })}>
+                        <div className="layout" style={{ border: this.layout === 'blank' ? 'solid 2px #5b9ddd' : '' }} onClick={action(() => { this.layout = 'blank'; this.createNewSlide(this.layout); })} />
+                        <div className="layout" style={{ border: this.layout === 'title' ? 'solid 2px #5b9ddd' : '' }} onClick={action(() => { this.layout = 'title'; this.createNewSlide(this.layout); })}>
                             <div className="title">Title</div>
                             <div className="subtitle">Subtitle</div>
                         </div>
-                        <div className="layout" style={{ border: this.layout === 'header' ? 'solid 2px #5b9ddd' : '' }} onClick={() => runInAction(() => { this.layout = 'header'; this.createNewSlide(this.layout); })}>
+                        <div className="layout" style={{ border: this.layout === 'header' ? 'solid 2px #5b9ddd' : '' }} onClick={action(() => { this.layout = 'header'; this.createNewSlide(this.layout); })}>
                             <div className="title" style={{ alignSelf: 'center', fontSize: 10 }}>Section header</div>
                         </div>
-                        <div className="layout" style={{ border: this.layout === 'content' ? 'solid 2px #5b9ddd' : '' }} onClick={() => runInAction(() => { this.layout = 'content'; this.createNewSlide(this.layout); })}>
+                        <div className="layout" style={{ border: this.layout === 'content' ? 'solid 2px #5b9ddd' : '' }} onClick={action(() => { this.layout = 'content'; this.createNewSlide(this.layout); })}>
                             <div className="title" style={{ alignSelf: 'center' }}>Title</div>
                             <div className="content">Text goes here</div>
                         </div>
@@ -845,39 +841,39 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                         {/* <div className="dropdown-textInput"> */}
                         <input className="ribbon-textInput" placeholder="..." type="text" name="fname" ref={this.inputRef} onChange={(e) => {
                             e.stopPropagation();
-                            runInAction(() => { (this.title = e.target.value) });
+                            runInAction(() => this.title = e.target.value);
                         }}></input>
                         {/* </div> */}
                     </div>
                     <div className="ribbon-box">
                         Choose type:
                         <div className="ribbon-doubleButton">
-                            <div title="Text" className={'ribbon-button'} style={{ background: this.addFreeform ? "" : "#aedef8" }} onClick={() => runInAction(() => { this.addFreeform = !this.addFreeform })}>Text</div>
-                            <div title="Freeform" className={'ribbon-button'} style={{ background: this.addFreeform ? "#aedef8" : "" }} onClick={() => runInAction(() => { this.addFreeform = !this.addFreeform })}>Freeform</div>
+                            <div title="Text" className={'ribbon-button'} style={{ background: this.addFreeform ? "" : "#aedef8" }} onClick={action(() => this.addFreeform = !this.addFreeform)}>Text</div>
+                            <div title="Freeform" className={'ribbon-button'} style={{ background: this.addFreeform ? "#aedef8" : "" }} onClick={action(() => this.addFreeform = !this.addFreeform)}>Freeform</div>
                         </div>
                     </div>
                     <div className="ribbon-box" style={{ display: this.addFreeform ? "grid" : "none" }}>
                         Preset layouts:
                         <div className="layout-container" style={{ height: this.openLayouts ? 'max-content' : '75px' }}>
-                            <div className="layout" style={{ border: this.layout === 'blank' ? 'solid 2px #5b9ddd' : '' }} onClick={() => runInAction(() => { this.layout = 'blank' })} />
-                            <div className="layout" style={{ border: this.layout === 'title' ? 'solid 2px #5b9ddd' : '' }} onClick={() => runInAction(() => { this.layout = 'title' })}>
+                            <div className="layout" style={{ border: this.layout === 'blank' ? 'solid 2px #5b9ddd' : '' }} onClick={action(() => this.layout = 'blank')} />
+                            <div className="layout" style={{ border: this.layout === 'title' ? 'solid 2px #5b9ddd' : '' }} onClick={action(() => this.layout = 'title')}>
                                 <div className="title">Title</div>
                                 <div className="subtitle">Subtitle</div>
                             </div>
-                            <div className="layout" style={{ border: this.layout === 'header' ? 'solid 2px #5b9ddd' : '' }} onClick={() => runInAction(() => { this.layout = 'header' })}>
+                            <div className="layout" style={{ border: this.layout === 'header' ? 'solid 2px #5b9ddd' : '' }} onClick={action(() => this.layout = 'header')}>
                                 <div className="title" style={{ alignSelf: 'center', fontSize: 10 }}>Section header</div>
                             </div>
-                            <div className="layout" style={{ border: this.layout === 'content' ? 'solid 2px #5b9ddd' : '' }} onClick={() => runInAction(() => { this.layout = 'content' })}>
+                            <div className="layout" style={{ border: this.layout === 'content' ? 'solid 2px #5b9ddd' : '' }} onClick={action(() => this.layout = 'content')}>
                                 <div className="title" style={{ alignSelf: 'center' }}>Title</div>
                                 <div className="content">Text goes here</div>
                             </div>
-                            <div className="layout" style={{ border: this.layout === 'twoColumns' ? 'solid 2px #5b9ddd' : '' }} onClick={() => runInAction(() => { this.layout = 'twoColumns' })}>
+                            <div className="layout" style={{ border: this.layout === 'twoColumns' ? 'solid 2px #5b9ddd' : '' }} onClick={action(() => this.layout = 'twoColumns')}>
                                 <div className="title" style={{ alignSelf: 'center', gridColumn: '1/3' }}>Title</div>
                                 <div className="content" style={{ gridColumn: 1, gridRow: 2 }}>Column one text</div>
                                 <div className="content" style={{ gridColumn: 2, gridRow: 2 }}>Column two text</div>
                             </div>
                         </div>
-                        <div className="open-layout" onClick={() => runInAction(() => { this.openLayouts = !this.openLayouts })}>
+                        <div className="open-layout" onClick={action(() => this.openLayouts = !this.openLayouts)}>
                             <FontAwesomeIcon style={{ transition: 'all 0.3s', transform: this.openLayouts ? 'rotate(180deg)' : 'rotate(0deg)' }} icon={"caret-down"} size={"lg"} />
                         </div>
                     </div>
@@ -974,10 +970,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
     }
 
     // For toggling the options when the user wants to select play
-    @action togglePlay = () => { this.playTools = !this.playTools; }
+    @action togglePlay = () => { this.playTools = !this.playTools; };
 
     // For toggling the options when the user wants to select play
-    @action togglePresent = () => { this.presentTools = !this.presentTools; }
+    @action togglePresent = () => { this.presentTools = !this.presentTools; };
 
     // Case in which the document has keyframes to navigate to next key frame
     @undoBatch
@@ -1381,9 +1377,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         if (doc && tagDocView) {
 
             const scale = tagDocView.childScaling();
-            console.log("childScaling: " + scale);
             const scale2 = tagDocView.props.ScreenToLocalTransform().Scale;
-            console.log("ScreenToLocal...Scale: " + scale2);
             let height = doc.offsetHeight;
             let width = doc.offsetWidth;
             let top = doc.offsetTop;
@@ -1544,7 +1538,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
     @undoBatch
     @action
     prevAppearFrame = (doc: Doc, i: number): void => {
-        console.log("prev");
         const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
         const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null);
         const appearFrame = Cast(doc.appearFrame, "number", null);
@@ -1595,7 +1588,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         if (activeItem) {
             return (
                 <>
-                    <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={() => runInAction(() => { this.newDocumentTools = !this.newDocumentTools; })}><FontAwesomeIcon icon={"plus"} />
+                    <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={action(() => this.newDocumentTools = !this.newDocumentTools)}><FontAwesomeIcon icon={"plus"} />
                         <FontAwesomeIcon className={`dropdown ${this.newDocumentTools ? "active" : ""}`} icon={"angle-down"} />
                     </div></Tooltip>
                     <div className="toolbar-divider" />
@@ -1636,7 +1629,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         } else {
             return (
                 <>
-                    <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={() => runInAction(() => { this.newDocumentTools = !this.newDocumentTools; })}>
+                    <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={action(() => this.newDocumentTools = !this.newDocumentTools)}>
                         <FontAwesomeIcon icon={"plus"} />
                         <FontAwesomeIcon className={`dropdown ${this.newDocumentTools ? "active" : ""}`} icon={"angle-down"} />
                     </div></Tooltip>
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 76d23ddfe..ab1de5529 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -577,20 +577,19 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         const xLoc: number = (nestDepth * 20);
         const width: number = 390 - xLoc;
         const height: number = 55 - (nestDepth * 5);
-        for (let i = 0; i < list.length; i++) {
-            const mainBullets: number = Number(list[i].getAttribute("data-bulletstyle"));
+        Array.from(list).forEach(listItem => {
+            const mainBullets: number = Number(listItem.getAttribute("data-bulletstyle"));
             if (mainBullets === nestDepth) {
-                if (list[i].childElementCount > 1) {
+                if (listItem.childElementCount > 1) {
                     b++;
                     nestCount++;
                     count = before ? count + nestCount + "." : nestCount + ".";
                     yLoc += height;
-                    const text = list[i].getElementsByTagName("p")[0].innerText;
+                    const text = listItem.getElementsByTagName("p")[0].innerText;
                     const length = text.length;
-                    console.log(yLoc);
                     const bullet1 = Docs.Create.TextDocument(count + " " + text, { title: "Slide text", _width: width, _height: height, x: xLoc, y: 10 + (yLoc), _fontSize: fontSize, backgroundColor: "rgba(0,0,0,0)", appearFrame: d ? d : b });
                     mainBulletList.push(bullet1);
-                    const newList = this.recursiveProgressivize(nestDepth + 1, list[i].getElementsByTagName("li"), b, yLoc, count);
+                    const newList = this.recursiveProgressivize(nestDepth + 1, listItem.getElementsByTagName("li"), b, yLoc, count);
                     mainBulletList.push.apply(mainBulletList, newList);
                     b += newList.length;
                     yLoc += newList.length * (55 - ((nestDepth + 1) * 5));
@@ -599,15 +598,13 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                     nestCount++;
                     count = before ? count + nestCount + "." : nestCount + ".";
                     yLoc += height;
-                    const text = list[i].innerText;
+                    const text = listItem.innerText;
                     const length = text.length;
-                    console.log(yLoc);
                     const bullet1 = Docs.Create.TextDocument(count + " " + text, { title: "Slide text", _width: width, _height: height, x: xLoc, y: 10 + (yLoc), _fontSize: fontSize, backgroundColor: "rgba(0,0,0,0)", appearFrame: d ? d : b });
                     mainBulletList.push(bullet1);
                 }
             }
-        }
-        console.log("b: " + b);
+        });
         return mainBulletList;
     }
 
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index 6e268be48..5af07c15d 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -903,8 +903,9 @@ export default class RichTextMenu extends AntimodeMenu {
             ref_node = pos.nodeBefore;
         }
         if (pos.nodeAfter !== null && pos.nodeAfter !== undefined) {
-            if (!pos.nodeBefore || this.view.state.selection.$from.pos !== this.view.state.selection.$to.pos)
+            if (!pos.nodeBefore || this.view.state.selection.$from.pos !== this.view.state.selection.$to.pos) {
                 ref_node = pos.nodeAfter;
+            }
         }
         if (!ref_node && pos.pos > 0) {
             let skip = false;
diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx
index e035ed0b8..11ffde9dd 100644
--- a/src/client/views/presentationview/PresElementBox.tsx
+++ b/src/client/views/presentationview/PresElementBox.tsx
@@ -259,7 +259,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
         const dragData = new DragManager.DocumentDragData(PresBox.Instance.sortArray().map(doc => doc));
         // let value = this.getValue(this._heading);
         // value = typeof value === "string" ? `"${value}"` : value;
-        let dragItem: HTMLElement[] = [];
+        const dragItem: HTMLElement[] = [];
         PresBox.Instance._dragArray.map(ele => {
             const drag = ele;
             drag.style.backgroundColor = "#d5dce2";
-- 
cgit v1.2.3-70-g09d2


From 988a16c4b69d1d5062bccf70295aa90c490f9e76 Mon Sep 17 00:00:00 2001
From: usodhi <61431818+usodhi@users.noreply.github.com>
Date: Thu, 6 Aug 2020 17:18:34 +0530
Subject: a bunch of commented stuff in propertiesview that is to be used for
 adding in the sharing panel customisation buttons

---
 .../collectionFreeForm/PropertiesView.scss         | 27 ++++++--
 .../collectionFreeForm/PropertiesView.tsx          | 80 ++++++++++++++++++----
 src/client/views/nodes/DocumentView.tsx            |  1 +
 3 files changed, 90 insertions(+), 18 deletions(-)

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

diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index 7df56115f..7b5d611f3 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -119,6 +119,19 @@
             font-size: 10px;
             padding: 10px;
             margin-left: 5px;
+
+            .change-buttons {
+                display: flex;
+
+                button {
+                    width: 5;
+                    height: 5;
+                }
+
+                input {
+                    width: 100%;
+                }
+            }
         }
     }
 
@@ -233,11 +246,15 @@
 
     .propertiesView-sharingTable {
 
+        // whatever's commented out - add it back in when adding the buttons
+
+        // border: 1.5px solid black;
         border: 1px solid black;
-        padding: 5px;
-        border-radius: 6px;
-        /* width: 170px; */
-        margin-right: 10px;
+        padding: 5px; // remove when adding buttons
+        border-radius: 6px; // remove when adding buttons
+        margin-right: 10px; // remove when adding buttons
+        // width: 100%;
+        // display: inline-table;
         background-color: #ececec;
         max-height: 130px;
         overflow-y: scroll;
@@ -245,9 +262,11 @@
         .propertiesView-sharingTable-item {
 
             display: flex;
+            // padding: 5px;
             padding: 3px;
             align-items: center;
             border-bottom: 0.5px solid grey;
+            cursor: pointer;
 
             &:hover .propertiesView-sharingTable-item-name {
                 overflow-x: unset;
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 31962837c..81202b126 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -2,13 +2,11 @@ import React = require("react");
 import { observer } from "mobx-react";
 import "./PropertiesView.scss";
 import { observable, action, computed, runInAction } from "mobx";
-import { Doc, Field, DocListCast, WidthSym, HeightSym, AclSym, AclPrivate, AclReadonly, AclAddonly, AclEdit, AclAdmin, Opt } from "../../../../fields/Doc";
-import { DocumentView } from "../../nodes/DocumentView";
+import { Doc, Field, WidthSym, HeightSym, AclSym, AclPrivate, AclReadonly, AclAddonly, AclEdit, AclAdmin, Opt, DocCastAsync } from "../../../../fields/Doc";
 import { ComputedField } from "../../../../fields/ScriptField";
 import { EditableView } from "../../EditableView";
 import { KeyValueBox } from "../../nodes/KeyValueBox";
 import { Cast, NumCast, StrCast } from "../../../../fields/Types";
-import { listSpec } from "../../../../fields/Schema";
 import { ContentFittingDocumentView } from "../../nodes/ContentFittingDocumentView";
 import { returnFalse, returnOne, emptyFunction, emptyPath, returnTrue, returnZero, returnEmptyFilter, Utils } from "../../../../Utils";
 import { Id } from "../../../../fields/FieldSymbols";
@@ -16,18 +14,18 @@ import { Transform } from "../../../util/Transform";
 import { PropertiesButtons } from "../../PropertiesButtons";
 import { SelectionManager } from "../../../util/SelectionManager";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { Tooltip, Checkbox, Divider } from "@material-ui/core";
+import { Tooltip, Checkbox } from "@material-ui/core";
 import SharingManager from "../../../util/SharingManager";
 import { DocumentType } from "../../../documents/DocumentTypes";
-import FormatShapePane from "./FormatShapePane";
 import { SharingPermissions, GetEffectiveAcl } from "../../../../fields/util";
 import { InkField } from "../../../../fields/InkField";
 import { undoBatch } from "../../../util/UndoManager";
 import { ColorState, SketchPicker } from "react-color";
-import AntimodeMenu from "../../AntimodeMenu";
 import "./FormatShapePane.scss";
-import { discovery_v1 } from "googleapis";
+// import * as fa from '@fortawesome/free-solid-svg-icons';
+// import { library } from "@fortawesome/fontawesome-svg-core";
 
+// library.add(fa.faPlus, fa.faMinus, fa.faCog);
 
 interface PropertiesViewProps {
     width: number;
@@ -58,6 +56,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @observable openLayout: boolean = true;
     @observable openAppearance: boolean = true;
     @observable openTransform: boolean = true;
+    // @observable selectedUser: string = "";
+    // @observable addButtonPressed: boolean = false;
 
     @computed get isInk() { return this.selectedDoc?.type === DocumentType.INK; }
 
@@ -277,8 +277,9 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     /**
      * @returns the options for the permissions dropdown.
      */
-    getPermissionsSelect(user: string) {
+    getPermissionsSelect(user: string, permission: string) {
         return <select className="permissions-select"
+            defaultValue={permission}
             onChange={e => this.changePermissions(e, user)}>
             {Object.values(SharingPermissions).map(permission => {
                 return (
@@ -318,12 +319,15 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     /**
      * @returns a row of the permissions panel
      */
-    sharingItem(name: string, effectiveAcl: symbol, permission?: string) {
-        return <div className="propertiesView-sharingTable-item">
+    sharingItem(name: string, effectiveAcl: symbol, permission: string) {
+        return <div className="propertiesView-sharingTable-item"
+        // style={{ backgroundColor: this.selectedUser === name ? "#bcecfc" : "" }}
+        // onPointerDown={action(() => this.selectedUser = this.selectedUser === name ? "" : name)}
+        >
             <div className="propertiesView-sharingTable-item-name" style={{ width: name !== "Me" ? "85px" : "80px" }}> {name} </div>
             {/* {name !== "Me" ? this.notifyIcon : null} */}
             <div className="propertiesView-sharingTable-item-permission">
-                {effectiveAcl === AclAdmin && permission !== "Owner" ? this.getPermissionsSelect(name) : permission}
+                {effectiveAcl === AclAdmin && permission !== "Owner" ? this.getPermissionsSelect(name, permission) : permission}
                 {permission === "Owner" ? this.expansionIcon : null}
             </div>
         </div>;
@@ -344,13 +348,21 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         const effectiveAcl = GetEffectiveAcl(this.selectedDoc!);
         const tableEntries = [];
 
+        // DocCastAsync(Doc.UserDoc().sidebarUsersDisplayed).then(sidebarUsersDisplayed => {
         if (this.selectedDoc![AclSym]) {
             for (const [key, value] of Object.entries(this.selectedDoc![AclSym])) {
                 const name = key.substring(4).replace("_", ".");
-                if (name !== Doc.CurrentUserEmail && name !== this.selectedDoc!.author) tableEntries.push(this.sharingItem(name, effectiveAcl, AclMap.get(value)!));
+                if (name !== Doc.CurrentUserEmail && name !== this.selectedDoc!.author/* && sidebarUsersDisplayed![name] !== false*/) tableEntries.push(this.sharingItem(name, effectiveAcl, AclMap.get(value)!));
             }
         }
 
+        //     if (Doc.UserDoc().sidebarUsersDisplayed) {
+        //         for (const [name, value] of Object.entries(sidebarUsersDisplayed!)) {
+        //             if (value === true && !this.selectedDoc![`ACL-${name.substring(8).replace(".", "_")}`]) tableEntries.push(this.sharingItem(name.substring(8), effectiveAcl, SharingPermissions.None));
+        //         }
+        //     }
+        // })
+
         // shifts the current user and the owner to the top of the doc.
         tableEntries.unshift(this.sharingItem("Me", effectiveAcl, Doc.CurrentUserEmail === this.selectedDoc!.author ? "Owner" : StrCast(this.selectedDoc![`ACL-${Doc.CurrentUserEmail.replace(".", "_")}`])));
         if (Doc.CurrentUserEmail !== this.selectedDoc!.author) tableEntries.unshift(this.sharingItem(StrCast(this.selectedDoc!.author), effectiveAcl, "Owner"));
@@ -558,7 +570,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     getField(key: string) {
         //if (this.selectedDoc) {
-        return Field.toString(this.selectedDoc[key] as Field);
+        return Field.toString(this.selectedDoc![key] as Field);
         // } else {
         //     return undefined as Opt<string>;
         // }
@@ -749,8 +761,18 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         </div>;
     }
 
-    render() {
+    /**
+     * Handles adding and removing members from the sharing panel
+     */
+    // handleUserChange = (selectedUser: string, add: boolean) => {
+    //     if (!Doc.UserDoc().sidebarUsersDisplayed) Doc.UserDoc().sidebarUsersDisplayed = new Doc;
+    //     DocCastAsync(Doc.UserDoc().sidebarUsersDisplayed).then(sidebarUsersDisplayed => {
+    //         sidebarUsersDisplayed![`display-${selectedUser}`] = add;
+    //         !add && runInAction(() => this.selectedUser = "");
+    //     });
+    // }
 
+    render() {
         if (!this.selectedDoc) {
             return <div className="propertiesView" style={{ width: this.props.width }}>
                 <div className="propertiesView-title" style={{ width: this.props.width }}>
@@ -800,6 +822,36 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 {!this.openSharing ? (null) :
                     <div className="propertiesView-sharing-content">
                         {this.sharingTable}
+                        {/* <div className="change-buttons">
+                            <button
+                                onPointerDown={action(() => this.addButtonPressed = !this.addButtonPressed)}
+                            >
+                                <FontAwesomeIcon icon={fa.faPlus} size={"sm"} style={{ marginTop: -3, marginLeft: -3 }} />
+                            </button>
+                            <button
+                                id="sharingProperties-removeUser"
+                                onPointerDown={() => this.handleUserChange(this.selectedUser, false)}
+                                style={{ backgroundColor: this.selectedUser ? "#121721" : "#777777" }}
+                            ><FontAwesomeIcon icon={fa.faMinus} size={"sm"} style={{ marginTop: -3, marginLeft: -3 }} /></button>
+                            <button onClick={() => SharingManager.Instance.open(this.selectedDocumentView!)}><FontAwesomeIcon icon={fa.faCog} size={"sm"} style={{ marginTop: -3, marginLeft: -3 }} /></button>
+                            {this.addButtonPressed ?
+                                // <input type="text" onKeyDown={this.handleKeyPress} /> :
+                                <select onChange={e => this.handleUserChange(e.target.value, true)}>
+                                    <option selected disabled hidden>
+                                        Add users
+                                    </option>
+                                    {SharingManager.Instance.users.map(user =>
+                                        (<option value={user.user.email}>
+                                            {user.user.email}
+                                        </option>)
+                                    )}
+                                    {GroupManager.Instance.getAllGroups().map(group =>
+                                        (<option value={StrCast(group.groupName)}>
+                                            {StrCast(group.groupName)}
+                                        </option>))}
+                                </select> :
+                                null}
+                        </div> */}
                     </div>}
             </div>
 
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 60075d5cf..46eabf15a 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -571,6 +571,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             alert("Can't delete the active workspace");
         } else {
             SelectionManager.DeselectAll();
+            this.props.Document.deleted = true;
             this.props.removeDocument?.(this.props.Document);
         }
     }
-- 
cgit v1.2.3-70-g09d2


From 3e4329b81d96f139f38eeb182afcbd8359dcd171 Mon Sep 17 00:00:00 2001
From: usodhi <61431818+usodhi@users.noreply.github.com>
Date: Thu, 6 Aug 2020 19:51:25 +0530
Subject: alias and acl related fixes

---
 src/client/documents/Documents.ts                    |  1 +
 src/client/views/collections/CollectionView.tsx      |  3 ++-
 .../collectionFreeForm/PropertiesView.tsx            | 20 +++++++++++---------
 src/fields/Doc.ts                                    |  4 ++--
 src/fields/util.ts                                   |  2 +-
 5 files changed, 17 insertions(+), 13 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 7719b3eef..61a44a39d 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -565,6 +565,7 @@ export namespace Docs {
             // without this, if a doc has no annotations but the user has AddOnly privileges, they won't be able to add an annotation because they would have needed to create the field's list which they don't have permissions to do.
 
             dataDoc[fieldKey + "-annotations"] = new List<Doc>();
+            dataDoc.aliases = new List<Doc>();
 
             proto.links = ComputedField.MakeFunction("links(self)");
 
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index dcd5a31f6..4d1cb670c 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -151,7 +151,8 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
                 if (this.props.Document[AclSym]) {
                     added.forEach(d => {
                         for (const [key, value] of Object.entries(this.props.Document[AclSym])) {
-                            distributeAcls(key, this.AclMap.get(value) as SharingPermissions, d, true);
+                            if (d.author === Doc.CurrentUserEmail && !d.aliasOf) distributeAcls(key, SharingPermissions.Admin, d, true);
+                            else distributeAcls(key, this.AclMap.get(value) as SharingPermissions, d, true);
                         }
                     });
                 }
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index d22c00b1f..5634a438a 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -25,6 +25,7 @@ import "./FormatShapePane.scss";
 import { discovery_v1 } from "googleapis";
 import { PresBox } from "../../nodes/PresBox";
 import { DocumentManager } from "../../../util/DocumentManager";
+import FormatShapePane from "./FormatShapePane";
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -51,8 +52,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @computed get selectedDocumentView() {
         if (SelectionManager.SelectedDocuments().length) {
             return SelectionManager.SelectedDocuments()[0];
-        } else if (PresBox.Instance._selectedArray.length >= 1) {
-            return DocumentManager.Instance.getDocumentView(PresBox.Instance.rootDoc);
+        } else if (PresBox.Instance?._selectedArray.length >= 1) {
+            return DocumentManager.Instance.getDocumentView(PresBox.Instance?.rootDoc);
         } else { return undefined; }
     }
     @computed get isPres(): boolean {
@@ -72,6 +73,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @observable openTransform: boolean = true;
     // @observable selectedUser: string = "";
     // @observable addButtonPressed: boolean = false;
+
     //Pres Trails booleans:
     @observable openAddSlide: boolean = true;
     @observable openPresentationTools: boolean = true;
@@ -957,9 +959,9 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                     <div className="propertiesView-name">
                         {this.editableTitle}
                         <div className="propertiesView-presSelected">
-                            {PresBox.Instance._selectedArray.length} selected
+                            {PresBox.Instance?._selectedArray.length} selected
                             <div className="propertiesView-selectedList">
-                                {PresBox.Instance.listOfSelected}
+                                {PresBox.Instance?.listOfSelected}
                             </div>
                         </div>
                     </div>
@@ -973,7 +975,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                             </div>
                         </div>
                         {this.openAddSlide ? <div className="propertiesView-settings-content">
-                            {PresBox.Instance.newDocumentDropdown}
+                            {PresBox.Instance?.newDocumentDropdown}
                         </div> : null}
                     </div>
                     <div className="propertiesView-sharing">
@@ -986,7 +988,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                             </div>
                         </div>
                         {this.openPresTransitions ? <div className="propertiesView-sharing-content">
-                            {PresBox.Instance.transitionDropdown}
+                            {PresBox.Instance?.transitionDropdown}
                         </div> : null}
                     </div>
                     <div className="propertiesView-sharing">
@@ -999,20 +1001,20 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                             </div>
                         </div>
                         {this.openPresProgressivize ? <div className="propertiesView-sharing-content">
-                            {PresBox.Instance.progressivizeDropdown}
+                            {PresBox.Instance?.progressivizeDropdown}
                         </div> : null}
                     </div>
                     <div className="propertiesView-sharing">
                         <div className="propertiesView-sharing-title"
                             onPointerDown={() => runInAction(() => { this.openSlideOptions = !this.openSlideOptions; })}
                             style={{ backgroundColor: this.openSlideOptions ? "black" : "" }}>
-                            &nbsp; <FontAwesomeIcon icon={"cog"} /> &nbsp; {PresBox.Instance.stringType} options
+                            &nbsp; <FontAwesomeIcon icon={"cog"} /> &nbsp; {PresBox.Instance?.stringType} options
                         <div className="propertiesView-sharing-title-icon">
                                 <FontAwesomeIcon icon={this.openSlideOptions ? "caret-down" : "caret-right"} size="lg" color="white" />
                             </div>
                         </div>
                         {this.openSlideOptions ? <div className="propertiesView-sharing-content">
-                            {PresBox.Instance.optionsDropdown}
+                            {PresBox.Instance?.optionsDropdown}
                         </div> : null}
                     </div>
                     <div className="propertiesView-sharing">
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 6163fedbb..6bfe91378 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -508,9 +508,9 @@ export namespace Doc {
         alias.aliasOf = doc;
         alias.title = ComputedField.MakeFunction(`renameAlias(this, ${Doc.GetProto(doc).aliasNumber = NumCast(Doc.GetProto(doc).aliasNumber) + 1})`);
         alias.author = Doc.CurrentUserEmail;
+        alias[AclSym] = doc[AclSym];
 
-        if (!doc.aliases) doc.aliases = new List<Doc>([alias]);
-        else Doc.AddDocToList(doc, "aliases", alias);
+        Doc.AddDocToList(doc[DataSym], "aliases", alias);
 
         return alias;
     }
diff --git a/src/fields/util.ts b/src/fields/util.ts
index 44a3317db..4c71572db 100644
--- a/src/fields/util.ts
+++ b/src/fields/util.ts
@@ -220,7 +220,7 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc
         // maps over the aliases of the document
         if (target.aliases) {
             DocListCast(target.aliases).map(alias => {
-                distributeAcls(key, acl, alias);
+                distributeAcls(key, acl, alias, inheritingFromCollection);
             });
         }
 
-- 
cgit v1.2.3-70-g09d2


From 33487aa34fd455acf5216cfee7913d6e36f390ed Mon Sep 17 00:00:00 2001
From: Geireann Lindfield Roberts <60007097+geireann@users.noreply.github.com>
Date: Fri, 7 Aug 2020 01:35:46 +0800
Subject: presentaiton options slightly reformatted :pear:

---
 src/client/views/PropertiesButtons.tsx             |  3 +-
 .../views/collections/CollectionDockingView.tsx    |  3 +-
 .../collectionFreeForm/PropertiesView.scss         | 37 +++++++++
 .../collectionFreeForm/PropertiesView.tsx          | 64 ++++++++--------
 src/client/views/nodes/PresBox.scss                |  8 +-
 src/client/views/nodes/PresBox.tsx                 | 89 ++++++++++------------
 .../views/nodes/formattedText/FormattedTextBox.tsx | 19 ++---
 .../views/presentationview/PresElementBox.scss     |  4 +-
 .../views/presentationview/PresElementBox.tsx      |  3 +-
 9 files changed, 128 insertions(+), 102 deletions(-)

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

diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index 55eb6c028..5c584d270 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -221,8 +221,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
                 <div className="propertiesButtons-linker"
                     style={{ backgroundColor: isPinned ? "white" : "", color: isPinned ? "black" : "white" }}
                     onClick={e => DockedFrameRenderer.PinDoc(targetDoc, isPinned)}>
-                    <FontAwesomeIcon className="documentdecorations-icon" size="lg" icon="map-pin"
-                    />
+                    <FontAwesomeIcon className="documentdecorations-icon" size="lg" icon="map-pin" />
                 </div>
 
                 <div className="propertiesButtons-title" style={{
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 7bd79b2ef..7e096fa37 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -873,9 +873,8 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
         return (
             <div className="miniPres"
                 style={{ width: 250, height: 30, background: '#323232' }}
-                onClick={() => document.addEventListener("keydown", PresBox.Instance.minimizeEvents, false)}
             >
-                {<div className="miniPresOverlay" onClick={() => document.addEventListener("keydown", PresBox.Instance.minimizeEvents, false)}>
+                {<div className="miniPresOverlay">
                     <div className="miniPres-button" onClick={PresBox.Instance.back}><FontAwesomeIcon icon={"arrow-left"} /></div>
                     <div className="miniPres-button" onClick={() => PresBox.Instance.startAutoPres(PresBox.Instance.itemIndex)}><FontAwesomeIcon icon={PresBox.Instance.layoutDoc.presStatus === "auto" ? "pause" : "play"} /></div>
                     <div className="miniPres-button" onClick={PresBox.Instance.next}><FontAwesomeIcon icon={"arrow-right"} /></div>
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
index 5b41db90e..3ae94efb7 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss
@@ -405,6 +405,43 @@
         }
 
     }
+
+    .propertiesView-presTrails {
+        border-bottom: 1px solid black;
+        //padding: 8.5px;
+
+        .propertiesView-presTrails-title {
+            font-weight: bold;
+            font-size: 12.5px;
+            padding: 4px;
+            display: flex;
+            color: white;
+            padding-left: 8px;
+            background-color: rgb(51, 51, 51);
+
+            &:hover {
+                cursor: pointer;
+            }
+
+            .propertiesView-presTrails-title-icon {
+                float: right;
+                right: 0;
+                position: absolute;
+                margin-left: 2px;
+                margin-right: 9px;
+
+                &:hover {
+                    cursor: pointer;
+                }
+            }
+        }
+
+        .propertiesView-presTrails-content {
+            font-size: 10px;
+            padding: 10px;
+            margin-left: 5px;
+        }
+    }
 }
 
 .inking-button {
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index 89f48fc65..cef2241c9 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -71,11 +71,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @observable openAppearance: boolean = true;
     @observable openTransform: boolean = true;
     //Pres Trails booleans:
-    @observable openAddSlide: boolean = true;
-    @observable openPresentationTools: boolean = true;
-    @observable openPresTransitions: boolean = true;
-    @observable openPresProgressivize: boolean = true;
-    @observable openSlideOptions: boolean = true;
+    @observable openPresTransitions: boolean = false;
+    @observable openPresProgressivize: boolean = false;
+    @observable openAddSlide: boolean = false;
+    @observable openSlideOptions: boolean = false;
 
     @observable inActions: boolean = false;
     @observable _controlBtn: boolean = false;
@@ -874,6 +873,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 </div>;
             }
             if (this.isPres) {
+                const selectedItem: boolean = PresBox.Instance._selectedArray.length > 0;
                 return <div className="propertiesView" style={{ width: this.props.width }} >
                     <div className="propertiesView-title" style={{ width: this.props.width }}>
                         Presentation
@@ -890,57 +890,57 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                             </div>
                         </div>
                     </div>
-                    <div className="propertiesView-settings">
-                        <div className="propertiesView-settings-title"
-                            onPointerDown={() => runInAction(() => { this.openAddSlide = !this.openAddSlide; })}
-                            style={{ backgroundColor: this.openAddSlide ? "black" : "" }}>
-                            &nbsp; <FontAwesomeIcon icon={"plus"} /> &nbsp; Add new slide
-                        <div className="propertiesView-settings-title-icon">
-                                <FontAwesomeIcon icon={this.openAddSlide ? "caret-down" : "caret-right"} size="lg" color="white" />
-                            </div>
-                        </div>
-                        {this.openAddSlide ? <div className="propertiesView-settings-content">
-                            {PresBox.Instance.newDocumentDropdown}
-                        </div> : null}
-                    </div>
-                    <div className="propertiesView-sharing">
-                        <div className="propertiesView-sharing-title"
+                    {!selectedItem ? (null) : <div className="propertiesView-presTrails">
+                        <div className="propertiesView-presTrails-title"
                             onPointerDown={() => runInAction(() => { this.openPresTransitions = !this.openPresTransitions; })}
                             style={{ backgroundColor: this.openPresTransitions ? "black" : "" }}>
                             &nbsp; <FontAwesomeIcon icon={"rocket"} /> &nbsp; Transitions
-                        <div className="propertiesView-sharing-title-icon">
+                        <div className="propertiesView-presTrails-title-icon">
                                 <FontAwesomeIcon icon={this.openPresTransitions ? "caret-down" : "caret-right"} size="lg" color="white" />
                             </div>
                         </div>
-                        {this.openPresTransitions ? <div className="propertiesView-sharing-content">
+                        {this.openPresTransitions ? <div className="propertiesView-presTrails-content">
                             {PresBox.Instance.transitionDropdown}
                         </div> : null}
-                    </div>
-                    <div className="propertiesView-sharing">
-                        <div className="propertiesView-sharing-title"
+                    </div>}
+                    {!selectedItem ? (null) : <div className="propertiesView-presTrails">
+                        <div className="propertiesView-presTrails-title"
                             onPointerDown={() => runInAction(() => { this.openPresProgressivize = !this.openPresProgressivize; })}
                             style={{ backgroundColor: this.openPresProgressivize ? "black" : "" }}>
                             &nbsp; <FontAwesomeIcon icon={"tasks"} /> &nbsp; Progressivize
-                        <div className="propertiesView-sharing-title-icon">
+                        <div className="propertiesView-presTrails-title-icon">
                                 <FontAwesomeIcon icon={this.openPresProgressivize ? "caret-down" : "caret-right"} size="lg" color="white" />
                             </div>
                         </div>
-                        {this.openPresProgressivize ? <div className="propertiesView-sharing-content">
+                        {this.openPresProgressivize ? <div className="propertiesView-presTrails-content">
                             {PresBox.Instance.progressivizeDropdown}
                         </div> : null}
-                    </div>
-                    <div className="propertiesView-sharing">
-                        <div className="propertiesView-sharing-title"
+                    </div>}
+                    {!selectedItem ? (null) : <div className="propertiesView-presTrails">
+                        <div className="propertiesView-presTrails-title"
                             onPointerDown={() => runInAction(() => { this.openSlideOptions = !this.openSlideOptions; })}
                             style={{ backgroundColor: this.openSlideOptions ? "black" : "" }}>
                             &nbsp; <FontAwesomeIcon icon={"cog"} /> &nbsp; {PresBox.Instance.stringType} options
-                        <div className="propertiesView-sharing-title-icon">
+                        <div className="propertiesView-presTrails-title-icon">
                                 <FontAwesomeIcon icon={this.openSlideOptions ? "caret-down" : "caret-right"} size="lg" color="white" />
                             </div>
                         </div>
-                        {this.openSlideOptions ? <div className="propertiesView-sharing-content">
+                        {this.openSlideOptions ? <div className="propertiesView-presTrails-content">
                             {PresBox.Instance.optionsDropdown}
                         </div> : null}
+                    </div>}
+                    <div className="propertiesView-presTrails">
+                        <div className="propertiesView-presTrails-title"
+                            onPointerDown={() => runInAction(() => { this.openAddSlide = !this.openAddSlide; })}
+                            style={{ backgroundColor: this.openAddSlide ? "black" : "" }}>
+                            &nbsp; <FontAwesomeIcon icon={"plus"} /> &nbsp; Add new slide
+                        <div className="propertiesView-presTrails-title-icon">
+                                <FontAwesomeIcon icon={this.openAddSlide ? "caret-down" : "caret-right"} size="lg" color="white" />
+                            </div>
+                        </div>
+                        {this.openAddSlide ? <div className="propertiesView-presTrails-content">
+                            {PresBox.Instance.newDocumentDropdown}
+                        </div> : null}
                     </div>
                     <div className="propertiesView-sharing">
                         <div className="propertiesView-sharing-title"
diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss
index 77e7924dd..a87b0e466 100644
--- a/src/client/views/nodes/PresBox.scss
+++ b/src/client/views/nodes/PresBox.scss
@@ -247,7 +247,7 @@ $light-background: #ececec;
         justify-self: left;
         margin-top: 5px;
         padding-left: 10px;
-        background-color: rgb(222, 222, 222);
+        background-color: $light-background;
         border: solid 1px black;
         min-width: 80px;
         max-width: 200px;
@@ -272,7 +272,7 @@ $light-background: #ececec;
             cursor: pointer;
             position: relative;
             height: 100%;
-            background: #d5dce2;
+            background: $light-background;
             display: flex;
             align-items: center;
             justify-content: center;
@@ -436,7 +436,7 @@ $light-background: #ececec;
 
             .presBox-dropdownOptions {
                 position: absolute;
-                top: 29px;
+                top: 24px;
                 left: -1px;
                 z-index: 200;
                 width: 85%;
@@ -461,7 +461,7 @@ $light-background: #ececec;
             background-color: $light-background;
             border-radius: 5px;
             font-size: 10;
-            height: 30;
+            height: 25;
             padding-left: 5px;
             align-items: center;
             margin-top: 5px;
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index efcea832d..a9daba675 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -371,11 +371,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
             if (srcContext.miniPres) {
                 srcContext.miniPres = false;
                 CollectionDockingView.AddRightSplit(this.rootDoc);
-                document.removeEventListener("keydown", this.minimizeEvents, false);
             } else {
                 srcContext.miniPres = true;
                 this.props.addDocTab?.(this.rootDoc, "close");
-                document.addEventListener("keydown", this.minimizeEvents, false);
             }
         }
     }
@@ -506,20 +504,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         }
     }
 
-    // Key events when the minimized player is active
-    @action
-    minimizeEvents = (e: KeyboardEvent) => {
-        e.stopPropagation();
-        e.preventDefault();
-        if (e.keyCode === 27) { // Escape key
-            this.layoutDoc.presStatus = "edit";
-        } if (e.keyCode === 37) { // left(37) / a(65) / up(38) to go back
-            this.back();
-        } if (e.keyCode === 39) { // right (39) / d(68) / down(40) to go to next
-            this.next();
-        }
-    }
-
     // Key for when the presentaiton is active (according to Selection Manager)
     @action
     keyEvents = (e: KeyboardEvent) => {
@@ -531,10 +515,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
             else this.layoutDoc.presStatus = "edit";
         } if ((e.metaKey || e.altKey) && e.keyCode === 65) { // Ctrl-A to select all
             if (this.layoutDoc.presStatus === "edit") this._selectedArray = this.childDocs;
-        } if (e.keyCode === 37) { // left(37) / a(65) / up(38) to go back
-            if (this.layoutDoc.presStatus !== "edit") this.back();
-        } if (e.keyCode === 39) { // right (39) / d(68) / down(40) to go to next
-            if (this.layoutDoc.presStatus !== "edit") this.next();
+        } if (e.keyCode === 37 || e.keyCode === 38) { // left(37) / a(65) / up(38) to go back
+            this.back();
+        } if (e.keyCode === 39 || e.keyCode === 40) { // right (39) / d(68) / down(40) to go to next
+            this.next();
         } if (e.keyCode === 32) { // spacebar to 'present' or autoplay
             if (this.layoutDoc.presStatus !== "edit") this.startAutoPres(0);
             else this.layoutDoc.presStatus = "manual";
@@ -720,7 +704,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                             <div className="ribbon-property"> {duration} s </div>
                         </div>
                         <input type="range" step="0.1" min="0.1" max="10" value={duration} style={{ display: targetDoc.type === DocumentType.AUDIO ? "none" : "block" }} className={"toolbar-slider"} id="duration-slider" onChange={(e: React.ChangeEvent<HTMLInputElement>) => { e.stopPropagation(); this.setDurationTime(e.target.value); }} />
-                        <div className={"slider-headers"} style={{ display: targetDoc.type === DocumentType.AUDIO ? "none" : "block" }}>
+                        <div className={"slider-headers"} style={{ display: targetDoc.type === DocumentType.AUDIO ? "none" : "grid" }}>
                             <div className="slider-text">Short</div>
                             <div className="slider-text">Medium</div>
                             <div className="slider-text">Long</div>
@@ -814,6 +798,20 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
                             <div className="ribbon-doubleButton" style={{ display: "flex" }}>
                                 <div className="ribbon-button" style={{ backgroundColor: activeItem.openDocument ? "#aedef8" : "" }} onClick={() => activeItem.openDocument = !activeItem.openDocument}>Open document</div>
                             </div>
+                            <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.COL ? "inline-flex" : "none" }}>
+                                <div className="ribbon-button" style={{ backgroundColor: activeItem.presPinView ? "#aedef8" : "" }}
+                                    onClick={() => {
+                                        activeItem.presPinView = !activeItem.presPinView;
+                                        if (activeItem.presPinView) {
+                                            const x = targetDoc._panX;
+                                            const y = targetDoc._panY;
+                                            const scale = targetDoc._viewScale;
+                                            activeItem.presPinViewX = x;
+                                            activeItem.presPinViewY = y;
+                                            activeItem.presPinViewScale = scale;
+                                        }
+                                    }}>Presentation pin view</div>
+                            </div>
                             <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.WEB ? "inline-flex" : "none" }}>
                                 <div className="ribbon-button" onClick={this.progressivizeText}>Store original website</div>
                             </div>
@@ -1592,35 +1590,26 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
 
     @computed get toolbar() {
         const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null);
-        if (activeItem) {
-            return (
-                <div id="toolbarContainer" className={'presBox-toolbar'} style={{ display: this.layoutDoc.presStatus === "edit" ? "inline-flex" : "none" }}>
-                    <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={action(() => this.newDocumentTools = !this.newDocumentTools)}>
-                        <FontAwesomeIcon icon={"plus"} />
-                        <FontAwesomeIcon className={`dropdown ${this.newDocumentTools ? "active" : ""}`} icon={"angle-down"} />
-                    </div></Tooltip>
-                    <div className="toolbar-divider" />
-                    <Tooltip title={<><div className="dash-tooltip">{"View paths"}</div></>}><div className={`toolbar-button ${this.pathBoolean ? "active" : ""}`}>
-                        <FontAwesomeIcon icon={"exchange-alt"} onClick={this.childDocs.length > 1 ? this.viewPaths : undefined} />
-                    </div></Tooltip>
-                    <Tooltip title={<><div className="dash-tooltip">{this.expandBoolean ? "Minimize all" : "Expand all"}</div></>}>
-                        <div className={`toolbar-button ${this.expandBoolean ? "active" : ""}`} onClick={() => { this.toggleExpand(); this.childDocs.forEach((doc, ind) => { if (this.expandBoolean) doc.presExpandInlineButton = true; else doc.presExpandInlineButton = false; }); }}>
-                            <FontAwesomeIcon icon={"eye"} />
-                        </div>
-                    </Tooltip>
-                    <div className="toolbar-divider" />
-                </div>
-            );
-        } else {
-            return (
-                <div id="toolbarContainer" className={'presBox-toolbar'}>
-                    <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={action(() => this.newDocumentTools = !this.newDocumentTools)}>
-                        <FontAwesomeIcon icon={"plus"} />
-                        <FontAwesomeIcon className={`dropdown ${this.newDocumentTools ? "active" : ""}`} icon={"angle-down"} />
-                    </div></Tooltip>
-                </div>
-            );
-        }
+        return (
+            <div id="toolbarContainer" className={'presBox-toolbar'} style={{ display: this.layoutDoc.presStatus === "edit" ? "inline-flex" : "none" }}>
+                <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={action(() => this.newDocumentTools = !this.newDocumentTools)}>
+                    <FontAwesomeIcon icon={"plus"} />
+                    <FontAwesomeIcon className={`dropdown ${this.newDocumentTools ? "active" : ""}`} icon={"angle-down"} />
+                </div></Tooltip>
+                <div className="toolbar-divider" />
+                <Tooltip title={<><div className="dash-tooltip">{"View paths"}</div></>}>
+                    <div style={{ opacity: this.childDocs.length > 1 ? 1 : 0.3 }} className={`toolbar-button ${this.pathBoolean ? "active" : ""}`} onClick={this.childDocs.length > 1 ? this.viewPaths : undefined}>
+                        <FontAwesomeIcon icon={"exchange-alt"} />
+                    </div>
+                </Tooltip>
+                <Tooltip title={<><div className="dash-tooltip">{this.expandBoolean ? "Minimize all" : "Expand all"}</div></>}>
+                    <div style={{ opacity: this.childDocs.length > 0 ? 1 : 0.3 }} className={`toolbar-button ${this.expandBoolean ? "active" : ""}`} onClick={() => { if (this.childDocs.length > 0) this.toggleExpand(); this.childDocs.forEach((doc, ind) => { if (this.expandBoolean) doc.presExpandInlineButton = true; else doc.presExpandInlineButton = false; }); }}>
+                        <FontAwesomeIcon icon={"eye"} />
+                    </div>
+                </Tooltip>
+                <div className="toolbar-divider" />
+            </div>
+        );
     }
 
     /**
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index af4bd77c7..cc37cf586 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -577,7 +577,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         const mainBulletText: string[] = [];
         const mainBulletList: Doc[] = [];
         if (list) {
-            const newBullets: Doc[] = this.recursiveProgressivize(1, list);
+            const newBullets: Doc[] = this.recursiveProgressivize(1, list)[0];
             mainBulletList.push.apply(mainBulletList, newBullets);
         }
         console.log(mainBulletList.length);
@@ -591,7 +591,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         this.props.addDocument?.(doc);
     }
 
-    recursiveProgressivize = (nestDepth: number, list: HTMLCollectionOf<HTMLLIElement>, d?: number, y?: number, before?: string): Doc[] => {
+    recursiveProgressivize = (nestDepth: number, list: HTMLCollectionOf<HTMLLIElement>, d?: number, y?: number, before?: string): [Doc[], number] => {
         const mainBulletList: Doc[] = [];
         let b = d ? d : 0;
         let yLoc = y ? y : 0;
@@ -607,29 +607,30 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
                 if (listItem.childElementCount > 1) {
                     b++;
                     nestCount++;
-                    count = before ? count + nestCount + "." : nestCount + ".";
                     yLoc += height;
+                    count = before ? count + nestCount + "." : nestCount + ".";
                     const text = listItem.getElementsByTagName("p")[0].innerText;
                     const length = text.length;
-                    const bullet1 = Docs.Create.TextDocument(count + " " + text, { title: "Slide text", _width: width, _height: height, x: xLoc, y: 10 + (yLoc), _fontSize: fontSize, backgroundColor: "rgba(0,0,0,0)", appearFrame: d ? d : b });
+                    const bullet1 = Docs.Create.TextDocument(count + " " + text, { title: "Slide text", _width: width, _autoHeight: true, x: xLoc, y: (yLoc), _fontSize: fontSize, backgroundColor: "rgba(0,0,0,0)", appearFrame: d ? d : b });
+                    // yLoc += NumCast(bullet1._height);
                     mainBulletList.push(bullet1);
                     const newList = this.recursiveProgressivize(nestDepth + 1, listItem.getElementsByTagName("li"), b, yLoc, count);
-                    mainBulletList.push.apply(mainBulletList, newList);
-                    b += newList.length;
+                    mainBulletList.push.apply(mainBulletList, newList[0]);
                     yLoc += newList.length * (55 - ((nestDepth + 1) * 5));
                 } else {
                     b++;
                     nestCount++;
-                    count = before ? count + nestCount + "." : nestCount + ".";
                     yLoc += height;
+                    count = before ? count + nestCount + "." : nestCount + ".";
                     const text = listItem.innerText;
                     const length = text.length;
-                    const bullet1 = Docs.Create.TextDocument(count + " " + text, { title: "Slide text", _width: width, _height: height, x: xLoc, y: 10 + (yLoc), _fontSize: fontSize, backgroundColor: "rgba(0,0,0,0)", appearFrame: d ? d : b });
+                    const bullet1 = Docs.Create.TextDocument(count + " " + text, { title: "Slide text", _width: width, _autoHeight: true, x: xLoc, y: (yLoc), _fontSize: fontSize, backgroundColor: "rgba(0,0,0,0)", appearFrame: d ? d : b });
+                    // yLoc += NumCast(bullet1._height);
                     mainBulletList.push(bullet1);
                 }
             }
         });
-        return mainBulletList;
+        return [mainBulletList, yLoc];
     }
 
     recordDictation = () => {
diff --git a/src/client/views/presentationview/PresElementBox.scss b/src/client/views/presentationview/PresElementBox.scss
index 3d730d7ac..1e776384a 100644
--- a/src/client/views/presentationview/PresElementBox.scss
+++ b/src/client/views/presentationview/PresElementBox.scss
@@ -4,7 +4,7 @@ $light-background: #ececec;
 
 .presElementBox-item {
     display: grid;
-    grid-template-columns: max-content max-content max-content;
+    grid-template-columns: max-content max-content max-content max-content;
     background-color: #d5dce2;
     font-family: Roboto;
     letter-spacing: normal;
@@ -122,7 +122,7 @@ $light-background: #ececec;
     padding-left: 10px;
     padding-right: 10px;
     letter-spacing: normal;
-    max-width: max-content;
+    width: max-content;
     text-overflow: ellipsis;
     overflow: hidden;
     white-space: pre;
diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx
index 816577847..a6dbb76ef 100644
--- a/src/client/views/presentationview/PresElementBox.tsx
+++ b/src/client/views/presentationview/PresElementBox.tsx
@@ -326,11 +326,12 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
                     <div className="presElementBox-number">
                         {`${this.indexInPres + 1}.`}
                     </div>
-                    <div ref={this._dragRef} className="presElementBox-name">
+                    <div ref={this._dragRef} className="presElementBox-name" style={{ maxWidth: (PresBox.Instance.toolbarWidth - 70) }}>
                         {`${this.targetDoc?.title}`}
                     </div>
                     <Tooltip title={<><div className="dash-tooltip">{"Movement speed"}</div></>}><div className="presElementBox-time" style={{ display: PresBox.Instance.toolbarWidth > 300 ? "block" : "none" }}>{this.transition}</div></Tooltip>
                     <Tooltip title={<><div className="dash-tooltip">{"Duration"}</div></>}><div className="presElementBox-time" style={{ display: PresBox.Instance.toolbarWidth > 300 ? "block" : "none" }}>{this.duration}</div></Tooltip>
+                    <Tooltip title={<><div className="dash-tooltip">{"Presentation pin view"}</div></>}><div className="presElementBox-time" style={{ fontWeight: 700, display: this.rootDoc.presPinView && PresBox.Instance.toolbarWidth > 300 ? "block" : "none" }}>V</div></Tooltip>
                     <Tooltip title={<><div className="dash-tooltip">{"Remove from presentation"}</div></>}><div
                         className="presElementBox-closeIcon"
                         onClick={e => {
-- 
cgit v1.2.3-70-g09d2


From 985c4eb599859d946833ee4ca42a5743b7d6caf8 Mon Sep 17 00:00:00 2001
From: Geireann Lindfield Roberts <60007097+geireann@users.noreply.github.com>
Date: Fri, 7 Aug 2020 02:15:04 +0800
Subject: keyEvent changes :key: :point_down:

---
 .../collectionFreeForm/PropertiesView.tsx          |  2 +-
 src/client/views/nodes/PresBox.tsx                 | 39 ++++++++++++++--------
 2 files changed, 26 insertions(+), 15 deletions(-)

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

diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
index cef2241c9..9c1cbec99 100644
--- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
+++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx
@@ -51,7 +51,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @computed get selectedDocumentView() {
         if (SelectionManager.SelectedDocuments().length) {
             return SelectionManager.SelectedDocuments()[0];
-        } else if (PresBox.Instance._selectedArray.length >= 1) {
+        } else if (PresBox.Instance._selectedArray.length) {
             return DocumentManager.Instance.getDocumentView(PresBox.Instance.rootDoc);
         } else { return undefined; }
     }
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index a9daba675..7b370e89b 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -27,7 +27,6 @@ import { CollectionFreeFormViewChrome } from "../collections/CollectionMenu";
 import { actionAsync } from "mobx-utils";
 import { SelectionManager } from "../../util/SelectionManager";
 import { AudioBox } from "./AudioBox";
-import { white } from "colors";
 
 type PresBoxSchema = makeInterface<[typeof documentSchema]>;
 const PresBoxDocument = makeInterface(documentSchema);
@@ -74,7 +73,23 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         }
         this.props.Document.presentationFieldKey = this.fieldKey; // provide info to the presElement script so that it can look up rendering information about the presBox
     }
-
+    @computed get selectedDocumentView() {
+        if (SelectionManager.SelectedDocuments().length) {
+            return SelectionManager.SelectedDocuments()[0];
+        } else if (PresBox.Instance._selectedArray.length) {
+            return DocumentManager.Instance.getDocumentView(PresBox.Instance.rootDoc);
+        } else { return undefined; }
+    }
+    @computed get isPres(): boolean {
+        if (this.selectedDoc?.type === DocumentType.PRES) {
+            document.addEventListener("keydown", this.keyEvents, true);
+            return true;
+        } else {
+            document.removeEventListener("keydown", this.keyEvents, true);
+            return false;
+        }
+    }
+    @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; }
 
     componentDidMount() {
         this.rootDoc.presBox = this.rootDoc;
@@ -84,14 +99,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         this.layoutDoc._gridGap = 5;
     }
 
-    onPointerOver = () => {
-        document.addEventListener("keydown", this.keyEvents, true);
-    }
-
-    onPointerLeave = () => {
-        document.removeEventListener("keydown", this.keyEvents, true);
-    }
-
     updateCurrentPresentation = () => {
         Doc.UserDoc().activePresentation = this.rootDoc;
     }
@@ -485,9 +492,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
     //Command click
     @action
     multiSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement) => {
-        this._selectedArray.push(this.childDocs[this.childDocs.indexOf(doc)]);
-        this._eleArray.push(ref);
-        this._dragArray.push(drag);
+        if (!this._selectedArray.includes(doc)) {
+            this._selectedArray.push(this.childDocs[this.childDocs.indexOf(doc)]);
+            this._eleArray.push(ref);
+            this._dragArray.push(drag);
+        }
     }
 
     //Shift click
@@ -1683,10 +1692,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
     }
 
     render() {
+        // calling this method for keyEvents
+        this.isPres;
         // needed to ensure that the childDocs are loaded for looking up fields
         this.childDocs.slice();
         const mode = StrCast(this.rootDoc._viewType) as CollectionViewType;
-        return <div onPointerOver={this.onPointerOver} onPointerLeave={this.onPointerLeave} className="presBox-cont" style={{ minWidth: this.layoutDoc.inOverlay ? 240 : undefined }} >
+        return <div className="presBox-cont" style={{ minWidth: this.layoutDoc.inOverlay ? 240 : undefined }} >
             {this.topPanel}
             {this.toolbar}
             {this.newDocumentToolbarDropdown}
-- 
cgit v1.2.3-70-g09d2

