From 077e4ba816afd35bba4622e53d4dca62b74bf292 Mon Sep 17 00:00:00 2001
From: geireann <geireann.lindfield@gmail.com>
Date: Thu, 19 Aug 2021 21:56:57 -0400
Subject: menu UI updates

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

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

diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 1969d728c..9ff1a0f61 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -124,6 +124,8 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                 tab.element[0].prepend(iconWrap);
                 tab._disposers.layerDisposer = reaction(() => ({ layer: tab.DashDoc.activeLayer, color: this.tabColor }),
                     ({ layer, color }) => {
+                        console.log("TabDocView: " + this.tabColor);
+                        console.log("lightOrDark: " + lightOrDark(this.tabColor));
                         const textColor = lightOrDark(this.tabColor); //not working with StyleProp.Color
                         titleEle.style.color = textColor;
                         titleEle.style.backgroundColor = "transparent";
-- 
cgit v1.2.3-70-g09d2


From bc0a3eabf5a7a5d6c2944e4c6f99a4fd50563b82 Mon Sep 17 00:00:00 2001
From: geireann <60007097+geireann@users.noreply.github.com>
Date: Sun, 22 Aug 2021 16:05:57 -0400
Subject: more updates

---
 src/client/util/CurrentUserUtils.ts           |  4 ++--
 src/client/util/Scripting.ts                  | 10 ++++++++-
 src/client/views/collections/TabDocView.tsx   |  4 ++--
 src/client/views/nodes/button/FontIconBox.tsx | 31 ++++++++++-----------------
 4 files changed, 24 insertions(+), 25 deletions(-)

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

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 0898221f1..2903b84e3 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -931,8 +931,8 @@ export class CurrentUserUtils {
             // { title: "Strikethrough", tooltip: "Strikethrough", btnType: ButtonType.ToggleButton, icon: "strikethrough", click: 'toggleStrikethrough()'},
             // { title: "Superscript", tooltip: "Superscript", btnType: ButtonType.ToggleButton, icon: "superscript", click: 'toggleSuperscript()'},
             // { title: "Subscript", tooltip: "Subscript", btnType: ButtonType.ToggleButton, icon: "subscript", click: 'toggleSubscript()'},
-            { title: "Highlight", toolTip: "Highlight", btnType: ButtonType.ColorButton, icon: "highlighter", ignoreClick: true, scriptDoc: Doc.UserDoc(), userColorBtn: 'userDoc._highlightColor' },
-            { title: "Text color", toolTip: "Text color", btnType: ButtonType.ColorButton, icon: "fill-drip", ignoreClick: true, scriptDoc: Doc.UserDoc(), script:'console.log("test")', userColorBtn: 'userDoc._textColor' },
+            { title: "Highlight", toolTip: "Highlight", btnType: ButtonType.ColorButton, icon: "highlighter", ignoreClick: true, script:'changeFontColor' },
+            { title: "Text color", toolTip: "Text color", btnType: ButtonType.ColorButton, icon: "highlighter", ignoreClick: true, script:'changeHighlightColor' },
         ];
     }
 
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index eac87d31e..aa7c23527 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -171,10 +171,18 @@ function Run(script: string | undefined, customParams: string[], diagnostics: an
             if (!options.editable) {
                 batch = Doc.MakeReadOnly();
             }
+            const result1 = compiledFunction.apply(thisParam, params);
+            
             const result = compiledFunction.apply(thisParam, params).apply(thisParam, argsArray);
             if (batch) {
                 batch.end();
             }
+
+            if (script.includes('toggleOverlay(true)')){
+                console.log("[Scripting.ts] r1: ", result1);
+                console.log("[Scripting.ts]: ", result);
+            }
+
             return { success: true, result };
         } catch (error) {
 
@@ -315,7 +323,7 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp
     }
     const paramString = paramList.join(", ");
     const funcScript = `(function(${paramString})${requiredType ? `: ${requiredType}` : ''} {
-        ${addReturn ? `return ${script};` : script}
+        ${addReturn ? `return ${script};` : `return ${script};`}
     })`;
     host.writeFile("file.ts", funcScript);
 
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 9ff1a0f61..00de36400 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -124,8 +124,8 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                 tab.element[0].prepend(iconWrap);
                 tab._disposers.layerDisposer = reaction(() => ({ layer: tab.DashDoc.activeLayer, color: this.tabColor }),
                     ({ layer, color }) => {
-                        console.log("TabDocView: " + this.tabColor);
-                        console.log("lightOrDark: " + lightOrDark(this.tabColor));
+                        // console.log("TabDocView: " + this.tabColor);
+                        // console.log("lightOrDark: " + lightOrDark(this.tabColor));
                         const textColor = lightOrDark(this.tabColor); //not working with StyleProp.Color
                         titleEle.style.color = textColor;
                         titleEle.style.backgroundColor = "transparent";
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index bc4b56a2d..aa3a1ada4 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -8,7 +8,7 @@ import { ColorState, SketchPicker } from 'react-color';
 import { Doc, StrListCast } from '../../../../fields/Doc';
 import { createSchema, makeInterface } from '../../../../fields/Schema';
 import { ScriptField } from '../../../../fields/ScriptField';
-import { BoolCast, Cast, StrCast } from '../../../../fields/Types';
+import { BoolCast, Cast, NumCast, StrCast } from '../../../../fields/Types';
 import { DocumentType } from '../../../documents/DocumentTypes';
 import { Scripting } from "../../../util/Scripting";
 import { SelectionManager } from '../../../util/SelectionManager';
@@ -277,15 +277,8 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
     }
 
     @computed get toggleButton() {
-        const numSelected = SelectionManager.Views().length;
-        const selectedDoc = numSelected > 0 ? SelectionManager.Views()[0].Document : undefined;
-
         const script: string = StrCast(this.rootDoc.script) + "(true)";
-        console.log(script);
-        const boolResult = ScriptField.MakeScript(script)?.script.run().success;
-        if (script.includes("toggleOverlay")) {
-            console.log("boolResult: " + boolResult);
-        }
+        const boolResult = ScriptField.MakeScript(script)?.script.run().result;
 
         const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
         const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
@@ -426,15 +419,15 @@ Scripting.addGlobal(function changeBackgroundColor(color?: string, checkResult?:
 // toggle: Set overlay status of selected document
 Scripting.addGlobal(function toggleOverlay(checkResult?: boolean) {
     const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
-    if (checkResult) {
-        return selected && selected.Document.z == 1;
+    if (checkResult && selected) {
+        console.log("z: ", NumCast(selected.Document.z) === 1);
+        return NumCast(selected.Document.z) === 1;
     }
     selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log("[FontIconBox.tsx] toggleOverlay failed");
 });
 
 // toggle: Set overlay status of selected document
 Scripting.addGlobal(function changeFont(font: string) {
-    // TODO: glr check if font selected and change selected font
     SelectionManager.Views().map(dv => dv.props.Document._fontFamily = font);
     console.log(font);
     Doc.UserDoc()._fontFamily = font;
@@ -443,40 +436,38 @@ Scripting.addGlobal(function changeFont(font: string) {
 
 // toggle: Set overlay status of selected document
 Scripting.addGlobal(function changeFontColor(color: string) {
-    // TODO: glr check if font selected and change selected font
     console.log(color);
     Doc.UserDoc()._fontColor = color;
 });
 
 // toggle: Set overlay status of selected document
 Scripting.addGlobal(function changeFontSize(size: string) {
-    // TODO: glr check if font selected and change selected font
     console.log(size);
     Doc.UserDoc()._fontSize = size;
 });
 
 Scripting.addGlobal(function toggleBold(checkResult?: boolean) {
     if (checkResult) {
-        console.log("got here");
         return Doc.UserDoc().bold;
     }
-    // TODO: glr check if font selected and change selected font
     SelectionManager.Views().map(dv => dv.props.Document.bold = !dv.props.Document.bold);
     Doc.UserDoc().bold = !Doc.UserDoc().bold;
     return Doc.UserDoc().bold;
 });
 
 Scripting.addGlobal(function toggleUnderline(checkResult?: boolean) {
-    if (checkResult) return Doc.UserDoc().underline;
-    // TODO: glr check if font selected and change selected font
+    if (checkResult) {
+        return Doc.UserDoc().underline;
+    }
     SelectionManager.Views().map(dv => dv.props.Document.underline = !dv.props.Document.underline);
     Doc.UserDoc().bold = !Doc.UserDoc().underline;
     return Doc.UserDoc().underline;
 });
 
 Scripting.addGlobal(function toggleItalic(checkResult?: boolean) {
-    if (checkResult) return Doc.UserDoc().italic;
-    // TODO: glr check if font selected and change selected font
+    if (checkResult) {
+        return Doc.UserDoc().italic;
+    }
     SelectionManager.Views().map(dv => dv.props.Document.italic = !dv.props.Document.italic);
     Doc.UserDoc().bold = !Doc.UserDoc().italic;
     return Doc.UserDoc().italic;
-- 
cgit v1.2.3-70-g09d2


From 101f04d82e49335fb2a55301a4ef4e7b04f081e6 Mon Sep 17 00:00:00 2001
From: geireann <60007097+geireann@users.noreply.github.com>
Date: Mon, 23 Aug 2021 22:15:40 -0400
Subject: menu getting closer :cry:

---
 src/client/documents/Documents.ts                  |   1 +
 src/client/util/CurrentUserUtils.ts                | 134 ++++++++++++--------
 src/client/views/collections/TabDocView.scss       |  30 +++--
 src/client/views/collections/TabDocView.tsx        |  12 +-
 .../collectionLinearView/CollectionLinearView.scss |   2 +-
 .../collectionLinearView/CollectionLinearView.tsx  |  10 +-
 src/client/views/global/globalCssVariables.scss    |   5 +
 src/client/views/global/globalEnums.tsx            |   4 +
 src/client/views/nodes/button/FontIconBox.scss     | 120 +++++++++++++++++-
 src/client/views/nodes/button/FontIconBox.tsx      | 137 +++++++++++++++++----
 10 files changed, 362 insertions(+), 93 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index b7ba6f1fe..57015e241 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -230,6 +230,7 @@ export class DocumentOptions {
     linearViewExpandable?: boolean; // can linear view be expanded
     linearViewToggleButton?: string; // button to open close linear view group
     linearViewSubMenu?: boolean;
+    linearViewFloating?: boolean;
     flexGap?: number; // Linear view flex gap
     flexDirection?: "unset" | "row" | "column" | "row-reverse" | "column-reverse";
 
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 2903b84e3..c7aa57ff0 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -38,7 +38,20 @@ import { SharingManager } from "./SharingManager";
 import { SnappingManager } from "./SnappingManager";
 import { UndoManager } from "./UndoManager";
 import { ButtonType } from "../views/nodes/button/FontIconBox";
-
+import { IconName } from "@fortawesome/fontawesome-svg-core";
+
+interface Button {
+    title?: string; 
+    toolTip?: string; 
+    icon?: string; 
+    btnType?: ButtonType; 
+    click?: string; 
+    switchToggle?: boolean;
+    script?: string; 
+    width?: number; 
+    list?: string[]; 
+    ignoreClick?: boolean;
+}
 
 export let resolvedPorts: { server: number, socket: number };
 const headerViewVersion = "0.1";
@@ -918,46 +931,71 @@ export class CurrentUserUtils {
     }
 
     static textTools(doc: Doc) {
-        return [
+        const tools:Button[] = 
+        [
             {
                 title: "Font", toolTip: "Font", width: 100, btnType: ButtonType.DropdownList, ignoreClick: true,
                 list: ["Roboto", "Roboto Mono", "Nunito", "Times New Roman", "Arial", "Georgia",
                     "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"],
                 script: 'changeFont'
             },
+            { title: "Font size", toolTip: "Font size", btnType: ButtonType.NumberButton, script: 'changeFontSize'},
             { title: "Bold", toolTip: "Bold (Ctrl+B)", btnType: ButtonType.ToggleButton, icon: "bold", click: 'toggleBold()', script: 'toggleBold' },
             { title: "Italic", toolTip: "Italic (Ctrl+I)", btnType: ButtonType.ToggleButton, icon: "italic", click: 'toggleItalic()', script: 'toggleItalic' },
             { title: "Underline", toolTip: "Underline (Ctrl+U)", btnType: ButtonType.ToggleButton, icon: "underline", click: 'toggleUnderline()', script: 'toggleUnderline' },
             // { title: "Strikethrough", tooltip: "Strikethrough", btnType: ButtonType.ToggleButton, icon: "strikethrough", click: 'toggleStrikethrough()'},
             // { title: "Superscript", tooltip: "Superscript", btnType: ButtonType.ToggleButton, icon: "superscript", click: 'toggleSuperscript()'},
             // { title: "Subscript", tooltip: "Subscript", btnType: ButtonType.ToggleButton, icon: "subscript", click: 'toggleSubscript()'},
-            { title: "Highlight", toolTip: "Highlight", btnType: ButtonType.ColorButton, icon: "highlighter", ignoreClick: true, script:'changeFontColor' },
+            { title: "Left align", toolTip: "Left align", btnType: ButtonType.ToggleButton, icon: "align-left", ignoreClick: true, script:'changeAlignment("left")' },
+            { title: "Center align", toolTip: "Center align", btnType: ButtonType.ToggleButton, icon: "align-center", ignoreClick: true, script:'changeAlignment("center")' },
+            { title: "Right align", toolTip: "Right align", btnType: ButtonType.ToggleButton, icon: "align-right", ignoreClick: true, script:'changeAlignment("right")' },
+
+            { title: "Highlight", toolTip: "Highlight", btnType: ButtonType.ColorButton, icon: "font", ignoreClick: true, script:'changeFontColor' },
             { title: "Text color", toolTip: "Text color", btnType: ButtonType.ColorButton, icon: "highlighter", ignoreClick: true, script:'changeHighlightColor' },
         ];
+        return tools;
     }
 
     static inkTools(doc: Doc) {
-        return [
+        const tools:Button[] = [
             { title: "Pen", toolTip: "Pen (Ctrl+P)", btnType: ButtonType.ToggleButton, icon: "pen", click: 'togglePen()', script: 'togglePen' },
-            { title: "Highlighter", toolTip: "Highlighter (Ctrl+H)", btnType: ButtonType.ToggleButton, icon: "highlighter", click: 'toggleHighlighter()', script: 'toggleHighlighter' },
+            { title: "Highlighter", toolTip: "Highlighter (Ctrl+H)", btnType: ButtonType.ToggleButton, icon: "highlighter", click: 'setHighlighter()', script: 'toggleHighlighter' },
             { title: "Circle", toolTip: "Circle (Ctrl+Shift+C)", btnType: ButtonType.ToggleButton, icon: "circle", click: 'toggleCircle()', script: 'toggleCircle' },
             { title: "Square", toolTip: "Square (Ctrl+Shift+S)", btnType: ButtonType.ToggleButton, icon: "square", click: 'toggleSquare()', script: 'toggleSquare' },
             { title: "Line", toolTip: "Line (Ctrl+Shift+L)", btnType: ButtonType.ToggleButton, icon: "fill-drip", click: 'toggleLine()', script: 'toggleLine' },
         ];
+        return tools;
     }
 
-    static webTools(doc: Doc) {
-        return [
-            {
-                title: "Font", toolTip: "Font", width: 100, btnType: ButtonType.DropdownList, ignoreClick: true,
-                list: ["Roboto", "Roboto Mono", "Nunito", "Times New Roman", "Arial", "Georgia",
-                    "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"],
-                script: 'changeFont'
+    static schemaTools(doc: Doc) {
+        const tools:Button[] = 
+        [
+            { 
+                title: "Show preview", 
+                toolTip: "Show preview of selected document", 
+                btnType: ButtonType.ToggleButton, 
+                switchToggle: true, 
+                icon: "eye", 
+                click: 'toggleSchemaShow()', 
+                script: 'toggleSchemaShow' 
             },
         ];
+        return tools;
+    }
+
+    static webTools(doc: Doc) {
+        const tools:Button[] = 
+        [
+            { title: "Back", toolTip: "Go back", btnType: ButtonType.ClickButton, icon: "arrow-left", click: 'webBack()' },
+            { title: "Forward", toolTip: "Go forward", btnType: ButtonType.ClickButton, icon: "arrow-right", click: 'webForward()' },
+            { title: "Reload", toolTip: "Reload webpage", btnType: ButtonType.ClickButton, icon: "redo-alt", click: 'webReload()' },
+            { title: "URL", toolTip: "URL", width: 150, btnType: ButtonType.EditableText, icon: "lock", script: 'webSetURL' },
+        ];
+
+        return tools;
     }
 
-    static async contextMenuBtnDescriptions(doc: Doc) {
+    static async contextMenuTools(doc: Doc) {
         return [
             {
                 title: "Perspective", toolTip: "View", width: 100, btnType: ButtonType.DropdownList, ignoreClick: true,
@@ -973,50 +1011,41 @@ export class CurrentUserUtils {
                 script: "changeBackgroundColor"
             },
             { title: "Overlay", toolTip: "Overlay", btnType: ButtonType.ToggleButton, icon: "layer-group", click: 'toggleOverlay()', script:'toggleOverlay'},
-            { title: "Text", type: "TextMenu" },
-            { title: "Ink & GFX", type: "InkMenu" },
-            // { title: "Ink Tools", type: "LinearMenu", icon: "pen-nib" },
-            // { title: "GFX Tools", type: "LinearMenu", icon: "shapes" },
-            // { title: "Alias", btnType: ButtonType.ClickButton, icon: "copy" },
+            { title: "Alias", btnType: ButtonType.ClickButton, icon: "copy" },
+            { title: "Text", type: "textTools", subMenu: true },
+            { title: "Ink & GFX", type: "inkTools", subMenu: true },
+            { title: "Web", type: "webTools", subMenu: true },
+            { title: "Schema", type: "schemaTools", subMenu: true }
         ];
     }
 
-    // Default context menu buttons
+    // Sets up the default context menu buttons
     static async setupContextMenuButtons(doc: Doc) {
         const docList: Doc[] = [];
 
-        const contextMenuBtns = (await CurrentUserUtils.contextMenuBtnDescriptions(doc)).map(({ title, width, list, toolTip, ignoreClick, icon, type, btnType, click, script }) => {
-            const textDocList: Doc[] = [];
-            if (type === "TextMenu") {
-                const textBtns = (CurrentUserUtils.textTools(doc)).map(({ title, width, list, toolTip, ignoreClick, icon, btnType, click, script, userColorBtn }) => {
-                    textDocList.push(Docs.Create.FontIconDocument({
-                        _nativeWidth: width ? width : 25,
-                        _nativeHeight: 25,
-                        _width: width ? width : 25,
-                        _height: 25,
-                        icon,
-                        toolTip,
-                        userColorBtn,
-                        script,
-                        btnType: btnType,
-                        btnList: new List<string>(list),
-                        ignoreClick: ignoreClick,
-                        _stayInCollection: true,
-                        _hideContextMenu: true,
-                        system: true,
-                        dontUndo: true,
-                        title,
-                        color: Colors.WHITE,
-                        backgroundColor: "transparent",
-                        _dropAction: "alias",
-                        _removeDropProperties: new List<string>(["dropAction", "_stayInCollection"]),
-                        onClick: click ? ScriptField.MakeScript(click, { doc: Doc.name }) : undefined
-                    }));
-                });
-                docList.push(CurrentUserUtils.linearButtonList({ linearViewSubMenu: true, flexGap: 5, ignoreClick: true, linearViewExpandable: true, icon:title, _height: 30, backgroundColor: "transparent" }, textDocList));
-            } else if (type === "InkMenu") {
-                const inkBtns = (CurrentUserUtils.inkTools(doc)).map(({ title, toolTip, icon, btnType, click }) => {
-                    textDocList.push(Docs.Create.FontIconDocument({
+        (await CurrentUserUtils.contextMenuTools(doc)).map(({ title, width, list, toolTip, ignoreClick, icon, type, btnType, click, script, subMenu }) => {
+            const menuDocList: Doc[] = [];
+            if (subMenu) {
+                // default is textTools
+                let tools: Button[];
+                switch(type){
+                    case "inkTools":
+                        tools = CurrentUserUtils.inkTools(doc);
+                        break;
+                    case "schemaTools":
+                        tools = CurrentUserUtils.schemaTools(doc);
+                        break;
+                    case "webTools":
+                        tools = CurrentUserUtils.webTools(doc);
+                        break;
+                    case "textTools":
+                        tools = CurrentUserUtils.textTools(doc);
+                        break;
+                    default:
+                        break;
+                }
+                tools.map(({ title, toolTip, icon, btnType, click, script, width, list, ignoreClick }) => {
+                    menuDocList.push(Docs.Create.FontIconDocument({
                         _nativeWidth: width ? width : 25,
                         _nativeHeight: 25,
                         _width: width ? width : 25,
@@ -1039,7 +1068,7 @@ export class CurrentUserUtils {
                         onClick: click ? ScriptField.MakeScript(click, { doc: Doc.name }) : undefined
                     }));
                 });
-                docList.push(CurrentUserUtils.linearButtonList({ linearViewSubMenu: true, flexGap: 5, ignoreClick: true, linearViewExpandable: true, icon:title, _height: 30, backgroundColor: "transparent" }, textDocList));
+                docList.push(CurrentUserUtils.linearButtonList({ linearViewSubMenu: true, flexGap: 5, ignoreClick: true, linearViewExpandable: true, icon:title, _height: 30, backgroundColor: "transparent" }, menuDocList));
             } else {
                 docList.push(Docs.Create.FontIconDocument({
                     _nativeWidth: width ? width : 25,
@@ -1070,6 +1099,7 @@ export class CurrentUserUtils {
             doc.contextMenuBtns = CurrentUserUtils.linearButtonList({ title: "menu buttons", flexGap: 0, ignoreClick: true, linearViewExpandable: false, _height: 35 }, docList);
         }
     }
+
     // sets up the default set of documents to be shown in the Overlay layer
     static setupOverlays(doc: Doc) {
         if (doc.myOverlayDocs === undefined) {
diff --git a/src/client/views/collections/TabDocView.scss b/src/client/views/collections/TabDocView.scss
index a963f1cb9..7f62ecaa0 100644
--- a/src/client/views/collections/TabDocView.scss
+++ b/src/client/views/collections/TabDocView.scss
@@ -1,3 +1,6 @@
+@import "../global/globalCssVariables.scss";
+
+
 input.lm_title:focus,
 input.lm_title {
     max-width: unset !important;
@@ -57,12 +60,11 @@ input.lm_title {
     }
 }
 
-.miniMap-hidden,
 .miniMap {
     position: absolute;
     overflow: hidden;
-    right: 10;
-    bottom: 10;
+    right: 15;
+    bottom: 15;
     border: solid 1px;
     box-shadow: black 0.4vw 0.4vw 0.8vw;
     width: 100%;
@@ -82,17 +84,21 @@ input.lm_title {
 }
 
 .miniMap-hidden {
+    cursor: pointer;
     position: absolute;
-    bottom: 0;
-    right: 0;
-    width: 45px;
-    height: 45px;
-    transform: translate(20px, 20px) rotate(45deg);
-    border-radius: 30px;
+    bottom: 5;
+    display: flex;
+    right: 5;
+    width: 25px;
+    height: 25px;
+    border-radius: 3px;
     padding: 2px;
+    justify-content: center;
+    align-items: center;
+    align-content: center;
+    background-color: $light-gray;
 
-    >svg {
-        margin-top: 3px;
-        transform: translate(0px, 7px);
+    &:hover {
+        box-shadow: none;
     }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 00de36400..a999512cc 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -34,6 +34,7 @@ import { CollectionView, CollectionViewType } from './CollectionView';
 import "./TabDocView.scss";
 import React = require("react");
 import Color = require('color');
+import { Colors, Shadows } from '../global/globalEnums';
 const _global = (window /* browser */ || global /* node */) as any;
 
 interface TabDocViewProps {
@@ -386,8 +387,15 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                     background={this.miniMapColor}
                     document={this._document}
                     tabView={this.tabView} />
-                <Tooltip style={{ display: this.disableMinimap() ? "none" : undefined }} key="ttip" title={<div className="dash-tooltip">{"toggle minimap"}</div>}>
-                    <div className="miniMap-hidden" onPointerDown={e => e.stopPropagation()} onClick={action(e => { e.stopPropagation(); this._document!.hideMinimap = !this._document!.hideMinimap; })} >
+                <Tooltip style={{ display: this.disableMinimap() ? "none" : undefined }} key="ttip" title={<div className="dash-tooltip">{this._document.hideMinimap ? "Open minimap" : "Close minimap"}</div>}>
+                    <div className="miniMap-hidden"
+                        style={{
+                            color: this._document.hideMinimap ? Colors.BLACK : Colors.WHITE,
+                            backgroundColor: this._document.hideMinimap ? Colors.LIGHT_GRAY : Colors.MEDIUM_BLUE,
+                            boxShadow: this._document.hideMinimap ? Shadows.STANDARD_SHADOW : undefined
+                        }}
+                        onPointerDown={e => e.stopPropagation()}
+                        onClick={action(e => { e.stopPropagation(); this._document!.hideMinimap = !this._document!.hideMinimap; })} >
                         <FontAwesomeIcon icon={"globe-asia"} size="lg" />
                     </div>
                 </Tooltip>
diff --git a/src/client/views/collections/collectionLinearView/CollectionLinearView.scss b/src/client/views/collections/collectionLinearView/CollectionLinearView.scss
index 44752e034..24c9bc9cb 100644
--- a/src/client/views/collections/collectionLinearView/CollectionLinearView.scss
+++ b/src/client/views/collections/collectionLinearView/CollectionLinearView.scss
@@ -89,7 +89,7 @@
             padding: 5;
             border-radius: 2px;
             height: 25;
-
+            min-width: 25;
             margin: 0;
             color: $white;
             display: flex;
diff --git a/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx b/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx
index 48f50cf2d..990c2e4b2 100644
--- a/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx
@@ -17,7 +17,7 @@ import { StyleProp } from '../../StyleProvider';
 import "./CollectionLinearView.scss";
 import { CollectionSubView } from '.././CollectionSubView';
 import { CollectionViewType } from '.././CollectionView';
-import { Colors } from '../../global/globalEnums';
+import { Colors, Shadows } from '../../global/globalEnums';
 
 
 type LinearDocument = makeInterface<[typeof documentSchema,]>;
@@ -112,6 +112,8 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
         const flexDir: any = StrCast(this.Document.flexDirection); // Specify direction of linear view content
         const flexGap: number = NumCast(this.Document.flexGap); // Specify the gap between linear view content
         const expandable: boolean = BoolCast(this.props.Document.linearViewExpandable); // Specify whether it is expandable or not
+        const floating: boolean = BoolCast(this.props.Document.linearViewFloating); // Specify whether it is expandable or not
+
         const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
         const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
         const icon: string = StrCast(this.props.Document.icon); // Menu opener toggle
@@ -121,7 +123,9 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
                 backgroundColor: backgroundColor === color ? "black" : BoolCast(this.layoutDoc.linearViewIsExpanded) ? undefined : Colors.LIGHT_GRAY
             }}
             onPointerDown={e => e.stopPropagation()} >
-            <div className="collectionLinearView-menuOpener">
+            <div className="collectionLinearView-menuOpener"
+                style={{ boxShadow: floating ? Shadows.STANDARD_SHADOW : undefined }}
+            >
                 {BoolCast(this.layoutDoc.linearViewIsExpanded) ? icon ? icon : "–" : icon ? icon : "+"}
             </div>
         </label>;
@@ -181,7 +185,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
                         </div>;
                     })}
                 </div>
-                {DocumentLinksButton.StartLink ? <span className="bottomPopup-background" style={{
+                {DocumentLinksButton.StartLink && StrCast(this.layoutDoc.title) === "docked buttons" ? <span className="bottomPopup-background" style={{
                     pointerEvents: "all"
                 }}
                     onPointerDown={e => e.stopPropagation()} >
diff --git a/src/client/views/global/globalCssVariables.scss b/src/client/views/global/globalCssVariables.scss
index a1baed7d9..2fd67a8dc 100644
--- a/src/client/views/global/globalCssVariables.scss
+++ b/src/client/views/global/globalCssVariables.scss
@@ -16,6 +16,7 @@ $close-red: #e48282;
 
 $drop-shadow: "#32323215";
 
+
 //padding
 $minimum-padding: 4px;
 $medium-padding: 16px;
@@ -48,6 +49,10 @@ $standard-border: solid 1px #9f9f9f;
 // border radius
 $standard-border-radius: 3px;
 
+// shadow
+$standard-box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3);
+
+
 $searchpanel-height: 32px;
 $mainTextInput-zindex: 999; // then text input overlay so that it's context menu will appear over decorations, etc
 $docDecorations-zindex: 998; // then doc decorations appear over everything else
diff --git a/src/client/views/global/globalEnums.tsx b/src/client/views/global/globalEnums.tsx
index 074a3aab3..56779c37c 100644
--- a/src/client/views/global/globalEnums.tsx
+++ b/src/client/views/global/globalEnums.tsx
@@ -36,4 +36,8 @@ export enum IconSizes {
 
 export enum Borders {
     STANDARD = "solid 1px #9F9F9F"
+}
+
+export enum Shadows {
+    STANDARD_SHADOW = "0px 3px 4px rgba(0, 0, 0, 0.3)"
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/button/FontIconBox.scss b/src/client/views/nodes/button/FontIconBox.scss
index fef99ce83..c1f5282d0 100644
--- a/src/client/views/nodes/button/FontIconBox.scss
+++ b/src/client/views/nodes/button/FontIconBox.scss
@@ -38,11 +38,15 @@
 
     &.clickBtn {
         cursor: pointer;
-        width: 40px;
 
         &:hover {
             background-color: rgba(0, 0, 0, 0.3) !important;
         }
+
+        svg {
+            width: 50% !important;
+            height: 50%;
+        }
     }
 
     &.tglBtn {
@@ -157,9 +161,58 @@
         }
     }
 
+    &.numBtn {
+        cursor: pointer;
+        background: transparent;
+
+        &.slider {
+            .numberBtn-slider {}
+
+            .menuButton-dropdownBox {
+                position: absolute;
+                width: fit-content;
+                height: fit-content;
+                top: 100%;
+                z-index: 21;
+                background-color: #e3e3e3;
+                box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3);
+                border-radius: $standard-border-radius;
+            }
+        }
+
+        &.dropdown {
+            .menuButton-dropdownList {
+                position: absolute;
+                width: fit-content;
+                height: fit-content;
+                top: 100%;
+                z-index: 21;
+                background-color: $white;
+                box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3);
+                padding: 1px;
+
+                .list-item {
+                    color: $black;
+                    width: 100%;
+                    height: 25px;
+                    font-weight: 400;
+                    display: flex;
+                    justify-content: left;
+                    align-items: center;
+                    padding-left: 5px;
+                }
+
+                .list-item:hover {
+                    background-color: lightgrey;
+                }
+            }
+        }
+    }
+
     &.drpDownBtn {
         cursor: pointer;
         background: transparent;
+        border: solid 0.5px grey;
 
         &.true {
             background: rgba(0, 0, 0, 0.3);
@@ -172,7 +225,7 @@
             top: 100%;
             background-color: #e3e3e3;
             box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3);
-            border-radius: 3px;
+            border-radius: $standard-border-radius;
         }
     }
 
@@ -208,4 +261,67 @@
         position: fixed;
     }
 
+}
+
+
+//TOGGLE
+
+.switch {
+    position: relative;
+    display: inline-block;
+    width: 50px;
+    height: 25px;
+}
+
+.switch input {
+    opacity: 0;
+    width: 0;
+    height: 0;
+}
+
+.slider {
+    position: absolute;
+    cursor: pointer;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-color: lightgrey;
+    -webkit-transition: .4s;
+    transition: .4s;
+}
+
+.slider:before {
+    position: absolute;
+    content: "";
+    height: 22px;
+    width: 22px;
+    left: 4px;
+    bottom: 4px;
+    background-color: white;
+    -webkit-transition: .4s;
+    transition: .4s;
+}
+
+input:checked+.slider {
+    background-color: $medium-blue;
+}
+
+input:focus+.slider {
+    box-shadow: 0 0 1px $medium-blue;
+}
+
+input:checked+.slider:before {
+    -webkit-transform: translateX(26px);
+    -ms-transform: translateX(26px);
+    transform: translateX(26px);
+}
+
+/* Rounded sliders */
+.slider.round {
+    border-radius: $standard-border-radius;
+}
+
+.slider.round:before {
+    border-radius: $standard-border-radius;
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index aa3a1ada4..46d92cd6e 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -3,9 +3,11 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Tooltip } from '@material-ui/core';
 import { action, computed, observable } from 'mobx';
 import { observer } from 'mobx-react';
+import { StringifyOptions } from 'querystring';
 import * as React from 'react';
 import { ColorState, SketchPicker } from 'react-color';
 import { Doc, StrListCast } from '../../../../fields/Doc';
+import { InkTool } from '../../../../fields/InkField';
 import { createSchema, makeInterface } from '../../../../fields/Schema';
 import { ScriptField } from '../../../../fields/ScriptField';
 import { BoolCast, Cast, NumCast, StrCast } from '../../../../fields/Types';
@@ -17,9 +19,11 @@ import { UndoManager } from '../../../util/UndoManager';
 import { CollectionViewType } from '../../collections/CollectionView';
 import { ContextMenu } from '../../ContextMenu';
 import { DocComponent } from '../../DocComponent';
+import { EditableView } from '../../EditableView';
 import { Colors } from '../../global/globalEnums';
 import { StyleProp } from '../../StyleProvider';
 import { FieldView, FieldViewProps } from '.././FieldView';
+import { RichTextMenu } from '../formattedText/RichTextMenu';
 import './FontIconBox.scss';
 const FontIconSchema = createSchema({
     icon: "string",
@@ -34,7 +38,8 @@ export enum ButtonType {
     ToggleButton = "tglBtn",
     ColorButton = "colorBtn",
     ToolButton = "toolBtn",
-    NumberButton = "numBtn"
+    NumberButton = "numBtn",
+    EditableText = "editableTxt"
 }
 
 export enum NumButtonType {
@@ -94,10 +99,15 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
     @computed get numberButton() {
         const numType: string = StrCast(this.rootDoc.numButtonType);
 
-        return (
-            <div className={`menuButton ${this.type}`}
-            >
+        const dropdown = numType ?
+            <div className="menuButton-dropdownBox"
+                style={{ left: 0 }}>
+                {/* DROPDOWN BOX CONTENTS */}
+            </div> : null;
 
+        return (
+            <div className={`menuButton ${this.type} ${numType}`}>
+                {this.rootDoc.dropDownOpen ? dropdown : null}
             </div>
         );
     }
@@ -130,7 +140,7 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
     }
 
     /**
-     * Dropdown button
+     * Dropdown list
      */
     @computed get dropdownListButton() {
         const active: string = StrCast(this.rootDoc.dropDownOpen);
@@ -221,7 +231,7 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
     }
 
     /**
-     * Colour button
+     * Color button
      */
     @computed get colorButton() {
         const active: string = StrCast(this.rootDoc.dropDownOpen);
@@ -229,10 +239,18 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
         const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
         const numSelected = SelectionManager.Views().length;
         const selectedDoc = numSelected > 0 ? SelectionManager.Views()[0].Document : undefined;
+
+        const script: string = StrCast(this.rootDoc.script);
+        const scriptCheck: string = script + "(undefined, true)";
+        const boolResult = ScriptField.MakeScript(scriptCheck)?.script.run().result;
+        console.log("[boolResul]: ", boolResult);
+
+        const colorOptions: string[] = ['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505',
+            '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B',
+            '#FFFFFF', '#f1efeb', 'transparent'];
+
         const colorBox = (func: (color: ColorState) => void) => <SketchPicker onChange={func} color={selectedDoc ? selectedDoc._backgroundColor : backgroundColor}
-            presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505',
-                '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B',
-                '#FFFFFF', '#f1efeb', 'transparent']} />;
+            presetColors={colorOptions} />;
         const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
             <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor, position: "absolute" }}>
                 {this.label}
@@ -242,10 +260,9 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
             style={{ borderBottomRightRadius: this.dropdown ? 0 : undefined }}>
             <FontAwesomeIcon icon={'caret-down'} color={color} size="sm" />
         </div>;
-        const script: string = StrCast(this.rootDoc.script);
         const click = (value: ColorState) => {
             const hex: string = value.hex;
-            const s = ScriptField.MakeScript(script + '("' + hex + '")');
+            const s = ScriptField.MakeScript(script + '("' + hex + '", false)');
             if (s) {
                 s.script.run().result;
             }
@@ -277,20 +294,47 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
     }
 
     @computed get toggleButton() {
-        const script: string = StrCast(this.rootDoc.script) + "(true)";
-        const boolResult = ScriptField.MakeScript(script)?.script.run().result;
+        // Determine the type of toggle button
+        const switchToggle: boolean = BoolCast(this.rootDoc.switchToggle);
+
+        // Script for running the toggle
+        const script: string = StrCast(this.rootDoc.script) + "()";
+        // Script for checking the outcome of the toggle
+        const checkScript: string = StrCast(this.rootDoc.script) + "(true)";
 
+        // Function to run the script
+        const runScript = () => ScriptField.MakeScript(script)?.script.run();
+        const checkResult = ScriptField.MakeScript(checkScript)?.script.run().result;
+
+        // Colors
         const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
         const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+
+        // Button label
         const label = !this.label || !Doc.UserDoc()._showLabel ? (null) :
             <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor, position: "absolute" }}>
                 {this.label}
             </div>;
+
         return (
-            <div className={`menuButton ${this.type}`} style={{ opacity: 1, backgroundColor: boolResult ? Colors.MEDIUM_BLUE : "transparent" }}>
-                <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={boolResult ? Colors.LIGHT_GRAY : Colors.LIGHT_GRAY} />
-                {label}
-            </div>
+            switchToggle ?
+                <div>
+                    <label className="switch">
+                        <input type="checkbox"
+                            checked={checkResult}
+                            onChange={runScript}
+                        />
+                        <span className="slider round"></span>
+                    </label>
+                </div>
+                :
+                <div className={`menuButton ${this.type}`}
+                    style={{ opacity: 1, backgroundColor: checkResult ? Colors.MEDIUM_BLUE : "transparent" }}
+                    onClick={this.layoutDoc.ignoreClick ? runScript : undefined}
+                >
+                    <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={checkResult ? Colors.LIGHT_GRAY : Colors.LIGHT_GRAY} />
+                    {label}
+                </div>
         );
     }
 
@@ -314,6 +358,19 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
         );
     }
 
+    @computed get editableText() {
+        const setValue = (value: string, shiftDown?: boolean): boolean => {
+            console.log("setValue");
+            return true;
+        };
+
+        return <div className={`menuButton ${this.type}`}>
+            TEST
+            <EditableView GetValue={() => ""} SetValue={setValue} contents="...">
+            </EditableView>
+        </div>;
+    }
+
 
     render() {
         const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
@@ -342,6 +399,8 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
         let button = this.defaultButton;
 
         switch (this.type) {
+            case ButtonType.EditableText:
+                button = this.editableText;
             case ButtonType.NumberButton:
                 button = this.numberButton;
                 break;
@@ -420,7 +479,6 @@ Scripting.addGlobal(function changeBackgroundColor(color?: string, checkResult?:
 Scripting.addGlobal(function toggleOverlay(checkResult?: boolean) {
     const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
     if (checkResult && selected) {
-        console.log("z: ", NumCast(selected.Document.z) === 1);
         return NumCast(selected.Document.z) === 1;
     }
     selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log("[FontIconBox.tsx] toggleOverlay failed");
@@ -429,17 +487,43 @@ Scripting.addGlobal(function toggleOverlay(checkResult?: boolean) {
 // toggle: Set overlay status of selected document
 Scripting.addGlobal(function changeFont(font: string) {
     SelectionManager.Views().map(dv => dv.props.Document._fontFamily = font);
-    console.log(font);
+    console.log("[changeFont]: ", font);
+    console.log(RichTextMenu.Instance.getActiveMarksOnSelection());
     Doc.UserDoc()._fontFamily = font;
     return Doc.UserDoc()._fontFamily;
 });
 
 // toggle: Set overlay status of selected document
-Scripting.addGlobal(function changeFontColor(color: string) {
-    console.log(color);
+Scripting.addGlobal(function changeFontColor(color?: string, checkResult?: boolean) {
+    const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
+    if (checkResult) {
+        if (selected) {
+            console.log("[Font color] (selected): " + StrCast(selected.Document._fontColor));
+            return selected.Document._fontColor;
+        } else {
+            console.log("[Font color] (global): " + StrCast(Doc.UserDoc()._fontColor));
+            return Doc.UserDoc()._fontColor;
+        }
+    }
+    Doc.UserDoc()._fontColor = color;
+});
+
+// toggle: Set overlay status of selected document
+Scripting.addGlobal(function changeFontHighlight(color?: string, checkResult?: boolean) {
+    const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
+    if (checkResult) {
+        if (selected) {
+            console.log("[Font color] (selected): " + StrCast(selected.Document._fontColor));
+            return selected.Document._fontColor;
+        } else {
+            console.log("[Font color] (global): " + StrCast(Doc.UserDoc()._fontColor));
+            return Doc.UserDoc()._fontColor;
+        }
+    }
     Doc.UserDoc()._fontColor = color;
 });
 
+
 // toggle: Set overlay status of selected document
 Scripting.addGlobal(function changeFontSize(size: string) {
     console.log(size);
@@ -471,4 +555,15 @@ Scripting.addGlobal(function toggleItalic(checkResult?: boolean) {
     SelectionManager.Views().map(dv => dv.props.Document.italic = !dv.props.Document.italic);
     Doc.UserDoc().bold = !Doc.UserDoc().italic;
     return Doc.UserDoc().italic;
+});
+
+Scripting.addGlobal(function setActiveInkTool(checkResult?: boolean, tool?: InkTool) {
+    if (checkResult) {
+        return Doc.UserDoc().activeInkTool === tool;
+    }
+    if (tool) {
+        Doc.UserDoc().activeInkTool = tool;
+    } else {
+        Doc.UserDoc().activeInkTool = InkTool.None;
+    }
 });
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 64fae6de1373f0db18ff98054227f217640952c2 Mon Sep 17 00:00:00 2001
From: geireann <geireann.lindfield@gmail.com>
Date: Tue, 31 Aug 2021 01:28:58 -0400
Subject: "Untitled Presentation" only created after a document is pinned

---
 src/client/util/CurrentUserUtils.ts         | 3 +--
 src/client/views/MainView.tsx               | 1 -
 src/client/views/collections/TabDocView.tsx | 6 ------
 src/server/DashUploadUtils.ts               | 2 +-
 4 files changed, 2 insertions(+), 10 deletions(-)

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

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index bcc47c355..aebcbcdff 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -579,7 +579,7 @@ export class CurrentUserUtils {
             { title: "Import", target: Cast(doc.myImportPanel, Doc, null), icon: "upload", click: 'selectMainMenu(self)' },
             { title: "Recently Closed", target: Cast(doc.myRecentlyClosedDocs, Doc, null), icon: "archive", click: 'selectMainMenu(self)' },
             { title: "Sharing", target: Cast(doc.mySharedDocs, Doc, null), icon: "users", click: 'selectMainMenu(self)', watchedDocuments: doc.mySharedDocs as Doc },
-            // { title: "Pres. Trails", target: Cast(doc.myPresentations, Doc, null), icon: "pres-trail", click: 'selectMainMenu(self)' },
+            { title: "Pres. Trails", target: Cast(doc.myPresentations, Doc, null), icon: "pres-trail", click: 'selectMainMenu(self)' },
             // { title: "Help", target: undefined as any, icon: "question-circle", click: 'selectMainMenu(self)' },
             // { title: "Settings", target: undefined as any, icon: "cog", click: 'selectMainMenu(self)' },
             { title: "User Doc", target: Cast(doc.myUserDoc, Doc, null), icon: "address-card", click: 'selectMainMenu(self)' },
@@ -1490,7 +1490,6 @@ export class CurrentUserUtils {
         DocListCast(dashboardDoc.data).forEach(doc => doc.dashboard = dashboardDoc);
         DocListCast(dashboardDoc.data)[1].data = ComputedField.MakeFunction(`dynamicOffScreenDocs(self.dashboard)`) as any;
 
-        Doc.AddDocToList(myPresentations, "data", presentation);
         userDoc.activePresentation = presentation;
 
         Doc.AddDocToList(dashboards, "data", dashboardDoc);
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index f082ba2c0..9047951ee 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -279,7 +279,6 @@ export class MainView extends React.Component {
             style={{
                 minWidth: `calc(100% - ${this._flyoutWidth + this.menuPanelWidth() + this.propertiesWidth()}px)`,
                 transform: LightboxView.LightboxDoc ? "scale(0.0001)" : undefined,
-                //TODO:glr width: `calc(100% - ${this._flyoutWidth + this.menuPanelWidth() + this.propertiesWidth()}px)`
             }}>
             {!this.mainContainer ? (null) : this.mainDocView}
         </div>;
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 28b074d35..889db1ef6 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -134,12 +134,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                         moreInfoDrag.style.backgroundColor = textColor;
                         tab.element[0].style.background = !layer ? color : "dimgrey";
                     }, { fireImmediately: true });
-                // TODO:glr fix
-                // tab.element[0].style.borderTopRightRadius = "8px";
-                // tab.element[0].children[1].appendChild(toggle);
-                // tab._disposers.layerDisposer = reaction(() =>
-                //     ({ layer: tab.DashDoc.activeLayer, color: this.tabColor }),
-                //     ({ layer, color }) => toggle.style.background = !layer ? color : "dimgrey", { fireImmediately: true });
             }
             // shifts the focus to this tab when another tab is dragged over it
             tab.element[0].onmouseenter = (e: MouseEvent) => {
diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts
index c32790df3..794126657 100644
--- a/src/server/DashUploadUtils.ts
+++ b/src/server/DashUploadUtils.ts
@@ -56,7 +56,7 @@ export namespace DashUploadUtils {
     const size = "content-length";
     const type = "content-type";
 
-    const { imageFormats, videoFormats, applicationFormats, audioFormats } = AcceptableMedia; //TODO:glr ASK BOB ABOUT THIS!
+    const { imageFormats, videoFormats, applicationFormats, audioFormats } = AcceptableMedia; //TODO:glr 
 
     export function uploadYoutube(videoId: string): Promise<Upload.FileResponse> {
         console.log("UPLOAD " + videoId);
-- 
cgit v1.2.3-70-g09d2


From 12d8267533d9b646247914e965b3cf7c32019e4b Mon Sep 17 00:00:00 2001
From: geireann <geireann.lindfield@gmail.com>
Date: Thu, 2 Sep 2021 04:45:01 -0400
Subject: Many updates

- Fixed image uploads so it clones rather than makes an alias
- Updated context menu
- Removed tools panel from novice mode in favour of ":" menu
- Added explainers to menus in novice mode
- Re-added the trails button
- Changed UI for text, PDF & websites so that it is more consistent
---
 src/client/documents/Documents.ts                  |  52 +++++----
 src/client/util/CurrentUserUtils.ts                |  93 ++++++++--------
 src/client/views/ContextMenu.scss                  |   2 +-
 src/client/views/ContextMenuItem.tsx               |   4 +-
 src/client/views/MainViewModal.scss                |   3 +-
 src/client/views/PropertiesButtons.scss            |  41 +++++--
 src/client/views/PropertiesButtons.tsx             |  53 +++++----
 src/client/views/SidebarAnnos.tsx                  |   3 +-
 src/client/views/StyleProvider.tsx                 |   4 +-
 .../views/collections/CollectionSchemaView.tsx     |   2 +-
 .../views/collections/CollectionStackingView.scss  |  24 +++++
 .../views/collections/CollectionStackingView.tsx   | 119 +++++++++++++++------
 .../views/collections/CollectionTreeView.tsx       |  95 ++++++++++++----
 src/client/views/collections/TabDocView.tsx        |   3 +-
 src/client/views/collections/TreeView.tsx          |   5 +-
 .../collectionLinearView/CollectionLinearView.scss |   6 +-
 .../collectionSchema/CollectionSchemaHeaders.tsx   |   2 +-
 .../collectionSchema/CollectionSchemaView.tsx      |   2 +-
 src/client/views/nodes/AudioBox.tsx                |   4 +-
 src/client/views/nodes/DocumentView.tsx            |   4 +-
 src/client/views/nodes/PDFBox.scss                 |  16 ++-
 src/client/views/nodes/PDFBox.tsx                  |  13 ++-
 src/client/views/nodes/WebBox.scss                 |   9 +-
 src/client/views/nodes/WebBox.tsx                  |  13 ++-
 src/client/views/nodes/button/FontIconBox.scss     |  29 ++++-
 src/client/views/nodes/button/FontIconBox.tsx      |  15 +--
 .../nodes/formattedText/FormattedTextBox.scss      |  21 +++-
 .../views/nodes/formattedText/FormattedTextBox.tsx |  16 ++-
 src/client/views/search/SearchBox.tsx              |   2 +-
 src/client/views/topbar/TopBar.scss                |   4 +-
 src/client/views/topbar/TopBar.tsx                 |   3 +-
 31 files changed, 460 insertions(+), 202 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index c4a713dc6..bd247bd01 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -59,6 +59,7 @@ import { WebBox } from "../views/nodes/WebBox";
 import { SearchBox } from "../views/search/SearchBox";
 import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo";
 import { DocumentType } from "./DocumentTypes";
+import { IconProp } from "@fortawesome/fontawesome-svg-core";
 const path = require('path');
 
 const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace("px", ""));
@@ -272,7 +273,12 @@ export class DocumentOptions {
     treeViewHideTitle?: boolean; // whether to hide the top document title of a tree view
     treeViewHideHeader?: boolean; // whether to hide the header for a document in a tree view
     treeViewHideHeaderFields?: boolean; // whether to hide the drop down options for tree view items.
-    treeViewShowClearButton?: boolean; // whether a clear button should be displayed 
+
+    // Action Button
+    buttonMenu?: boolean; // whether a action button should be displayed 
+    buttonMenuDoc?: Doc;
+    explainer?:string;
+
     treeViewOpenIsTransient?: boolean; // ignores the treeViewOpen Doc flag, allowing a treeViewItem's expand/collapse state to be independent of other views of the same document in the same or any other tree view
     _treeViewOpen?: boolean; // whether this document is expanded in a tree view  (note: need _ and regular versions since this can be specified for both proto and layout docs)
     treeViewOpen?: boolean; // whether this document is expanded in a tree view
@@ -1165,7 +1171,7 @@ export namespace DocUtils {
 
     export function addDocumentCreatorMenuItems(docTextAdder: (d: Doc) => void, docAdder: (d: Doc) => void, x: number, y: number, simpleMenu: boolean = false): void {
         !simpleMenu && ContextMenu.Instance.addItem({
-            description: "Add Note ...",
+            description: "Quick Notes",
             subitems: DocListCast((Doc.UserDoc()["template-notes"] as Doc).data).map((note, i) => ({
                 description: ":" + StrCast(note.title),
                 event: undoBatch((args: { x: number, y: number }) => {
@@ -1178,12 +1184,12 @@ export namespace DocUtils {
                     textDoc[textDoc.layoutKey] = note;
                     docTextAdder(textDoc);
                 }),
-                icon: "eye"
+                icon: StrCast(note.icon) as IconProp
             })) as ContextMenuProps[],
-            icon: "eye"
+            icon: "sticky-note"
         });
-        ContextMenu.Instance.addItem({
-            description: ":=math", event: () => {
+        const math:ContextMenuProps = ({
+            description: ":Math", event: () => {
                 const created = Docs.Create.EquationDocument();
                 if (created) {
                     created.author = Doc.CurrentUserEmail;
@@ -1194,25 +1200,27 @@ export namespace DocUtils {
                     EquationBox.SelectOnLoad = created[Id];
                     docAdder?.(created);
                 }
-            }, icon: "compress-arrows-alt"
+            }, icon: "calculator"
         });
+        const documentList:ContextMenuProps[] = DocListCast(Cast(Doc.UserDoc().myItemCreators, Doc, null)?.data).filter(btnDoc => !btnDoc.hidden).map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)).filter(doc => doc && doc !== Doc.UserDoc().emptyPresentation).map((dragDoc, i) => ({
+            description: ":" + StrCast(dragDoc.title),
+            event: undoBatch((args: { x: number, y: number }) => {
+                const newDoc = Doc.copyDragFactory(dragDoc);
+                if (newDoc) {
+                    newDoc.author = Doc.CurrentUserEmail;
+                    newDoc.x = x;
+                    newDoc.y = y;
+                    if (newDoc.type === DocumentType.RTF) FormattedTextBox.SelectOnLoad = newDoc[Id];
+                    docAdder?.(newDoc);
+                }
+            }),
+            icon: Doc.toIcon(dragDoc),
+        })) as ContextMenuProps[]; 
+        documentList.push(math)
         ContextMenu.Instance.addItem({
             description: "Create document",
-            subitems: DocListCast(Cast(Doc.UserDoc().myItemCreators, Doc, null)?.data).filter(btnDoc => !btnDoc.hidden).map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)).filter(doc => doc && doc !== Doc.UserDoc().emptyPresentation).map((dragDoc, i) => ({
-                description: ":" + StrCast(dragDoc.title),
-                event: undoBatch((args: { x: number, y: number }) => {
-                    const newDoc = Doc.copyDragFactory(dragDoc);
-                    if (newDoc) {
-                        newDoc.author = Doc.CurrentUserEmail;
-                        newDoc.x = x;
-                        newDoc.y = y;
-                        if (newDoc.type === DocumentType.RTF) FormattedTextBox.SelectOnLoad = newDoc[Id];
-                        docAdder?.(newDoc);
-                    }
-                }),
-                icon: Doc.toIcon(dragDoc),
-            })) as ContextMenuProps[],
-            icon: "eye"
+            subitems: documentList,
+            icon: "file"
         });
     }// applies a custom template to a document.  the template is identified by it's short name (e.g, slideView not layout_slideView)
     export function makeCustomViewClicked(doc: Doc, creator: Opt<(documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc>, templateSignature: string = "custom", docLayoutTemplate?: Doc) {
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index f12ac02f3..f6ec74482 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -84,7 +84,7 @@ export class CurrentUserUtils {
                 title: "NEW MOBILE BUTTON",
                 onClick: undefined,
             },
-                [this.ficon({
+                [this.createToolButton({
                     ignoreClick: true,
                     icon: "mobile",
                     btnType: ButtonType.ToolButton,
@@ -92,7 +92,7 @@ export class CurrentUserUtils {
                 }),
                 this.mobileTextContainer({},
                     [this.mobileButtonText({}, "NEW MOBILE BUTTON"), this.mobileButtonInfo({}, "You can customize this button and make it your own.")])]);
-            doc["template-mobile-button"] = CurrentUserUtils.ficon({
+            doc["template-mobile-button"] = CurrentUserUtils.createToolButton({
                 onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'),
                 dragFactory: new PrefetchProxy(queryTemplate) as any as Doc, title: "mobile button", icon: "mobile", btnType: ButtonType.ToolButton,
             });
@@ -107,7 +107,7 @@ export class CurrentUserUtils {
                 { _width: 400, _height: 300, title: "slideView", _xMargin: 3, _yMargin: 3, system: true }
             );
             slideTemplate.isTemplateDoc = makeTemplate(slideTemplate);
-            doc["template-button-slides"] = CurrentUserUtils.ficon({
+            doc["template-button-slides"] = CurrentUserUtils.createToolButton({
                 onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'),
                 dragFactory: new PrefetchProxy(slideTemplate) as any as Doc, title: "presentation slide", icon: "address-card",
                 btnType: ButtonType.ToolButton
@@ -154,7 +154,7 @@ export class CurrentUserUtils {
             };
             linkTemplate.header = new RichTextField(JSON.stringify(rtf2), "");
 
-            doc["template-button-link"] = CurrentUserUtils.ficon({
+            doc["template-button-link"] = CurrentUserUtils.createToolButton({
                 onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'),
                 dragFactory: new PrefetchProxy(linkTemplate) as any as Doc, title: "link view", icon: "window-maximize", system: true,
                 btnType: ButtonType.ToolButton
@@ -186,7 +186,7 @@ export class CurrentUserUtils {
             const box = MulticolumnDocument([/*no, */ yes, name], { title: "value", _width: 120, _height: 35, system: true });
             box.isTemplateDoc = makeTemplate(box, true, "switch");
 
-            doc["template-button-switch"] = CurrentUserUtils.ficon({
+            doc["template-button-switch"] = CurrentUserUtils.createToolButton({
                 onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'),
                 dragFactory: new PrefetchProxy(box) as any as Doc, title: "data switch", icon: "toggle-on", system: true,
                 btnType: ButtonType.ToolButton
@@ -236,7 +236,7 @@ export class CurrentUserUtils {
             short.title = "A Short Description";
             long.title = "Long Description";
 
-            doc["template-button-detail"] = CurrentUserUtils.ficon({
+            doc["template-button-detail"] = CurrentUserUtils.createToolButton({
                 onDragStart: ScriptField.MakeFunction('copyDragFactory(this.dragFactory)'),
                 dragFactory: new PrefetchProxy(detailView) as any as Doc,
                 title: "detailView",
@@ -275,7 +275,7 @@ export class CurrentUserUtils {
     static setupNoteTemplates(doc: Doc) {
         if (doc["template-note-Note"] === undefined) {
             const noteView = Docs.Create.TextDocument("", {
-                title: "text", isTemplateDoc: true, backgroundColor: "yellow", system: true,
+                title: "text", isTemplateDoc: true, backgroundColor: "yellow", system: true, icon: "sticky-note",
                 _fontFamily: StrCast(Doc.UserDoc()._fontFamily), _fontSize: StrCast(Doc.UserDoc()._fontSize),
             });
             noteView.isTemplateDoc = makeTemplate(noteView, true, "Note");
@@ -283,7 +283,7 @@ export class CurrentUserUtils {
         }
         if (doc["template-note-Idea"] === undefined) {
             const noteView = Docs.Create.TextDocument("", {
-                title: "text", backgroundColor: "pink", system: true,
+                title: "text", backgroundColor: "pink", system: true, icon: "lightbulb",
                 _fontFamily: StrCast(Doc.UserDoc()._fontFamily), _fontSize: StrCast(Doc.UserDoc()._fontSize),
             });
             noteView.isTemplateDoc = makeTemplate(noteView, true, "Idea");
@@ -291,7 +291,7 @@ export class CurrentUserUtils {
         }
         if (doc["template-note-Topic"] === undefined) {
             const noteView = Docs.Create.TextDocument("", {
-                title: "text", backgroundColor: "lightblue", system: true,
+                title: "text", backgroundColor: "lightblue", system: true, icon: "book-open",
                 _fontFamily: StrCast(Doc.UserDoc()._fontFamily), _fontSize: StrCast(Doc.UserDoc()._fontSize),
             });
             noteView.isTemplateDoc = makeTemplate(noteView, true, "Topic");
@@ -467,7 +467,7 @@ export class CurrentUserUtils {
             ((doc.emptyHeader as Doc).proto as Doc)["dragFactory-count"] = 0;
         }
         if (doc.emptyComparison === undefined) {
-            doc.emptyComparison = Docs.Create.ComparisonDocument({ title: "compare", _width: 300, _height: 300, system: true, cloneFieldFilter: new List<string>(["system"]) });
+            doc.emptyComparison = Docs.Create.ComparisonDocument({ title: "comparison box", _width: 300, _height: 300, system: true, cloneFieldFilter: new List<string>(["system"]) });
         }
         if (doc.emptyScript === undefined) {
             doc.emptyScript = Docs.Create.ScriptingDocument(undefined, { _width: 200, _height: 250, title: "script", system: true, cloneFieldFilter: new List<string>(["system"]) });
@@ -512,7 +512,7 @@ export class CurrentUserUtils {
             { toolTip: "Tap to create a progressive slide", title: "Slide", icon: "file", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptySlide as Doc },
             { toolTip: "Tap to create a cat image in a new pane, drag for a cat image", title: "Image", icon: "cat", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyImage as Doc },
             { toolTip: "Tap to create a comparison box in a new pane, drag for a comparison box", title: "Compare", icon: "columns", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyComparison as Doc, noviceMode: true },
-            { toolTip: "Tap to create a screen grabber in a new pane, drag for a screen grabber", title: "Grab", icon: "photo-video", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyScreenshot as Doc, noviceMode: true },
+            { toolTip: "Tap to create a screen grabber in a new pane, drag for a screen grabber", title: "Grab", icon: "photo-video", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyScreenshot as Doc },
             { toolTip: "Tap to create a videoWall", title: "Wall", icon: "photo-video", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyWall as Doc },
             { toolTip: "Tap to create an audio recorder in a new pane, drag for an audio recorder", title: "Audio", icon: "microphone", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyAudio as Doc, noviceMode: true },
             { toolTip: "Tap to create a button in a new pane, drag for a button", title: "Button", icon: "bolt", click: 'openOnRight(copyDragFactory(this.dragFactory))', drag: 'copyDragFactory(this.dragFactory)', dragFactory: doc.emptyButton as Doc },
@@ -561,7 +561,7 @@ export class CurrentUserUtils {
         if (dragCreatorSet === undefined) {
             doc.myItemCreators = new PrefetchProxy(Docs.Create.MasonryDocument(creatorBtns, {
                 title: "Basic Item Creators", _showTitle: "title", _xMargin: 0, _stayInCollection: true, _hideContextMenu: true, _chromeHidden: true,
-                _forceActive: true, _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true,
+                _autoHeight: true, _width: 500, _height: 300, _fitWidth: true, _columnWidth: 40, ignoreClick: true, _lockedPosition: true,
                 dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), system: true
             }));
         } else {
@@ -574,29 +574,31 @@ export class CurrentUserUtils {
         return [
             { title: "Dashboards", target: Cast(doc.myDashboards, Doc, null), icon: "desktop", click: 'selectMainMenu(self)' },
             { title: "Search", target: Cast(doc.mySearchPanel, Doc, null), icon: "search", click: 'selectMainMenu(self)' },
-            { title: "My Files", target: Cast(doc.myFilesystem, Doc, null), icon: "file", click: 'selectMainMenu(self)' },
-            { title: "Tools", target: Cast(doc.myTools, Doc, null), icon: "wrench", click: 'selectMainMenu(self)' },
-            { title: "Import", target: Cast(doc.myImportDocs, Doc, null), icon: "upload", click: 'selectMainMenu(self)' },
+            { title: "File Manager", target: Cast(doc.myFilesystem, Doc, null), icon: "folder-open", click: 'selectMainMenu(self)' },
+            { title: "Tools", target: Cast(doc.myTools, Doc, null), icon: "wrench", click: 'selectMainMenu(self)', hidden: "IsNoviceMode()" },
+            { title: "Uploads", target: Cast(doc.myUploadDocs, Doc, null), icon: "upload", click: 'selectMainMenu(self)' },
             { title: "Recently Closed", target: Cast(doc.myRecentlyClosedDocs, Doc, null), icon: "archive", click: 'selectMainMenu(self)' },
             { title: "Sharing", target: Cast(doc.mySharedDocs, Doc, null), icon: "users", click: 'selectMainMenu(self)', watchedDocuments: doc.mySharedDocs as Doc },
             { title: "Trails", target: Cast(doc.myTrails, Doc, null), icon: "pres-trail", click: 'selectMainMenu(self)' },
-            { title: "User Doc", target: Cast(doc.myUserDoc, Doc, null), icon: "address-card", click: 'selectMainMenu(self)' },
+            { title: "User Doc", target: Cast(doc.myUserDoc, Doc, null), icon: "address-card", click: 'selectMainMenu(self)', hidden: "IsNoviceMode()" },
         ];
     }
 
     static async setupMenuPanel(doc: Doc, sharingDocumentId: string, linkDatabaseId: string) {
         if (doc.menuStack === undefined) {
             await this.setupSharingSidebar(doc, sharingDocumentId, linkDatabaseId);  // sets up the right sidebar collection for mobile upload documents and sharing
-            const menuBtns = (await CurrentUserUtils.menuBtnDescriptions(doc)).map(({ title, target, icon, click, watchedDocuments }) =>
+            const menuBtns = (await CurrentUserUtils.menuBtnDescriptions(doc)).map(({ title, target, icon, click, watchedDocuments, hidden }) =>
                 Docs.Create.FontIconDocument({
                     icon,
                     btnType: ButtonType.MenuButton,
                     _stayInCollection: true,
                     _hideContextMenu: true,
+                    _chromeHidden: true,
                     system: true,
                     dontUndo: true,
                     title,
                     target,
+                    hidden: hidden ? ComputedField.MakeFunction("IsNoviceMode()") as any : undefined,
                     _dropAction: "alias",
                     _removeDropProperties: new List<string>(["dropAction", "_stayInCollection"]),
                     _width: 60,
@@ -611,8 +613,6 @@ export class CurrentUserUtils {
                     this.searchBtn = menuBtn;
                 }
             });
-            // hack -- last button is assumed to be the userDoc
-            menuBtns[menuBtns.length - 1].hidden = ComputedField.MakeFunction("IsNoviceMode()");
 
             menuBtns.forEach(menuBtn => {
                 if (menuBtn.title === "Search") {
@@ -684,7 +684,7 @@ export class CurrentUserUtils {
                 onClick: data.click ? ScriptField.MakeScript(data.click) : undefined,
                 backgroundColor: data.backgroundColor, system: true
             },
-                [this.ficon({ ignoreClick: true, icon: data.icon, backgroundColor: "rgba(0,0,0,0)", system: true, btnType: ButtonType.ClickButton, }), this.mobileTextContainer({}, [this.mobileButtonText({}, data.title), this.mobileButtonInfo({}, data.info)])])
+                [this.createToolButton({ ignoreClick: true, icon: data.icon, backgroundColor: "rgba(0,0,0,0)", system: true, btnType: ButtonType.ClickButton, }), this.mobileTextContainer({}, [this.mobileButtonText({}, data.title), this.mobileButtonInfo({}, data.info)])])
         );
     }
 
@@ -820,6 +820,7 @@ export class CurrentUserUtils {
             const removeDashboard = ScriptField.MakeScript('removeDashboard(self)');
             (doc.myDashboards as any as Doc).childContextMenuScripts = new List<ScriptField>([newDashboard!, shareDashboard!, removeDashboard!]);
             (doc.myDashboards as any as Doc).childContextMenuLabels = new List<string>(["Create New Dashboard", "Share Dashboard", "Remove Dashboard"]);
+            (doc.myDashboards as any as Doc).childContextMenuIcons = new List<string>(["plus", "share", "times"]);
             // (doc.myDashboards as any as Doc).childContextMenuScripts = new List<ScriptField>([newDashboard!, toggleTheme!, toggleComic!, snapshotDashboard!, shareDashboard!, removeDashboard!]);
             // (doc.myDashboards as any as Doc).childContextMenuLabels = new List<string>(["Create New Dashboard", "Toggle Theme Colors", "Toggle Comic Mode", "Snapshot Dashboard", "Share Dashboard", "Remove Dashboard"]);
         }
@@ -860,18 +861,21 @@ export class CurrentUserUtils {
     }
 
     static setupRecentlyClosedDocs(doc: Doc) {
-        // setup Recently Closed library item
         if (doc.myRecentlyClosedDocs === undefined) {
-            const clearDocs = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript(`getProto(self).data = new List([])`), toolTip: "Empty", _stayInCollection: true, _hideContextMenu: true, title: "Empty", btnType: ButtonType.TextButton, _width: 200, buttonText: "Empty Recently Closed", icon: "trash", system: true });
-            doc.myRecentlyClosedDocs = new PrefetchProxy(Docs.Create.TreeDocument([clearDocs], {
-                title: "My Recently Closed", _showTitle: "title", treeViewShowClearButton: true, childHideLinkButton: true,
+            const clearAll = ScriptField.MakeScript(`getProto(self).data = new List([])`);
+            const clearDocsButton:Doc = Docs.Create.FontIconDocument({ onClick: clearAll, _forceActive: true, toolTip: "Empty recently closed", _stayInCollection: true, _hideContextMenu: true, title: "Empty", btnType: ButtonType.ClickButton, _width: 30, _height: 30, buttonText: "Empty", icon: "trash", system: true });
+            doc.myRecentlyClosedDocs = new PrefetchProxy(Docs.Create.TreeDocument([], {
+                title: "My Recently Closed", _showTitle: "title", buttonMenu: true, buttonMenuDoc: clearDocsButton, childHideLinkButton: true,
                 treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias",
                 treeViewTruncateTitleWidth: 150, ignoreClick: true,
-                _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true
+                _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true,
+                explainer: "Documents that you close will appear here so you can easily access them again. You can choose to clear this menu in which case you might lose these documents."
+
             }));
-            const clearAll = ScriptField.MakeScript(`getProto(self).data = new List([])`);
             (doc.myRecentlyClosedDocs as any as Doc).contextMenuScripts = new List<ScriptField>([clearAll!]);
-            (doc.myRecentlyClosedDocs as any as Doc).contextMenuLabels = new List<string>(["Clear All"]);
+            (doc.myRecentlyClosedDocs as any as Doc).contextMenuLabels = new List<string>(["Empty recently closed"]);
+            (doc.myRecentlyClosedDocs as any as Doc).contextMenuIcons = new List<string>(["trash"]);
+
         }
     }
 
@@ -916,7 +920,7 @@ export class CurrentUserUtils {
     static async setupSidebarButtons(doc: Doc) {
         CurrentUserUtils.setupSidebarContainer(doc);
         await CurrentUserUtils.setupToolsBtnPanel(doc);
-        CurrentUserUtils.setupImportSidebar(doc);
+        CurrentUserUtils.setupUploadSidebar(doc);
         CurrentUserUtils.setupDashboards(doc);
         CurrentUserUtils.setupPresentations(doc);
         CurrentUserUtils.setupFilesystem(doc);
@@ -930,17 +934,17 @@ export class CurrentUserUtils {
         _lockedPosition: true, system: true, flexDirection: "row"
     })) as any as Doc
 
-    static ficon = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({
-        ...opts, _dropAction: "alias", _removeDropProperties: new List<string>(["_dropAction", "stayInCollection"]), _nativeWidth: 40, _nativeHeight: 40, _width: 40, _height: 40, system: true
+    static createToolButton = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({
+        ...opts, btnType: ButtonType.ToolButton, _forceActive: true, _dropAction: "alias", _removeDropProperties: new List<string>(["_dropAction", "stayInCollection"]), _nativeWidth: 40, _nativeHeight: 40, _width: 40, _height: 40, system: true
     })) 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
     static setupDockedButtons(doc: Doc) {
         if (doc["dockedBtn-undo"] === undefined) {
-            doc["dockedBtn-undo"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("undo()"), dontUndo: true, _stayInCollection: true, btnType: ButtonType.ToolButton, _dropAction: "alias", _hideContextMenu: true, _removeDropProperties: new List<string>(["dropAction", "_hideContextMenu", "stayInCollection"]), toolTip: "Click to undo", title: "undo", icon: "undo-alt", system: true });
+            doc["dockedBtn-undo"] = CurrentUserUtils.createToolButton({ onClick: ScriptField.MakeScript("undo()"), _width: 30, _height: 30, dontUndo: true, _stayInCollection: true, btnType: ButtonType.ToolButton, _dropAction: "alias", _hideContextMenu: true, _removeDropProperties: new List<string>(["dropAction", "_hideContextMenu", "stayInCollection"]), toolTip: "Click to undo", title: "undo", icon: "undo-alt", system: true });
         }
         if (doc["dockedBtn-redo"] === undefined) {
-            doc["dockedBtn-redo"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("redo()"), dontUndo: true, _stayInCollection: true, btnType: ButtonType.ToolButton, _dropAction: "alias", _hideContextMenu: true, _removeDropProperties: new List<string>(["dropAction", "_hideContextMenu", "stayInCollection"]), toolTip: "Click to redo", title: "redo", icon: "redo-alt", system: true });
+            doc["dockedBtn-redo"] = CurrentUserUtils.createToolButton({ onClick: ScriptField.MakeScript("redo()"), _width: 30, _height: 30, dontUndo: true, _stayInCollection: true, btnType: ButtonType.ToolButton, _dropAction: "alias", _hideContextMenu: true, _removeDropProperties: new List<string>(["dropAction", "_hideContextMenu", "stayInCollection"]), toolTip: "Click to redo", title: "redo", icon: "redo-alt", system: true });
         }
         if (doc.dockedBtns === undefined) {
             doc.dockedBtns = CurrentUserUtils.linearButtonList({ title: "docked buttons", _height: 40, flexGap: 0, linearViewFloating: true, linearViewIsExpanded: true, linearViewExpandable: true, ignoreClick: true }, [doc["dockedBtn-undo"] as Doc, doc["dockedBtn-redo"] as Doc]);
@@ -1039,7 +1043,7 @@ export class CurrentUserUtils {
             // { title: "Alias", btnType: ButtonType.ClickButton, icon: "copy", hidden: 'selectedDocumentType()' }, // Only when a document is selected 
             { title: "Text", type: "textTools", subMenu: true, expanded: 'selectedDocumentType("rtf")' }, // Always available
             { title: "Ink", type: "inkTools", subMenu: true, expanded: 'selectedDocumentType("ink")' }, // Always available
-            // { title: "Web", type: "webTools", subMenu: true, hidden: 'selectedDocumentType("web")' }, // Only when Web is selected
+            { title: "Web", type: "webTools", subMenu: true, hidden: 'selectedDocumentType("web")' }, // Only when Web is selected
             { title: "Schema", type: "schemaTools", subMenu: true, hidden: 'selectedDocumentType(undefined, "schema")' } // Only when Schema is selected
         ];
     }
@@ -1172,13 +1176,15 @@ export class CurrentUserUtils {
             }
             doc.myLinkDatabase = new PrefetchProxy(linkDocs);
         }
+        // TODO:glr NOTE: treeViewHideTitle & _showTitle may be confusing, treeViewHideTitle is for the editable title (just for tree view), _showTitle is to show the Document title for any document
         if (doc.mySharedDocs === undefined) {
             let sharedDocs = Docs.newAccount ? undefined : await DocServer.GetRefField(sharingDocumentId + "outer");
             if (!sharedDocs) {
                 sharedDocs = Docs.Create.TreeDocument([], {
                     title: "My SharedDocs", childDropAction: "alias", system: true, contentPointerEvents: "all", childLimitHeight: 0, _yMargin: 50, _gridGap: 15,
-                    _showTitle: "title", ignoreClick: true, _lockedPosition: true, "acl-Public": SharingPermissions.Augment, "_acl-Public": SharingPermissions.Augment,
+                    _showTitle: "title", treeViewHideTitle: true, ignoreClick: true, _lockedPosition: true, "acl-Public": SharingPermissions.Augment, "_acl-Public": SharingPermissions.Augment,
                     _chromeHidden: true, boxShadow: "0 0",
+                    explainer: "All of the documents that you receive will appear here. They must be shared by other users. If you receive a Dashboard you can add it to your Dashboards by right clicking and clicking 'Add to Dashboards'"
                 }, sharingDocumentId + "outer", sharingDocumentId);
                 (sharedDocs as Doc)["acl-Public"] = (sharedDocs as Doc)[DataSym]["acl-Public"] = SharingPermissions.Augment;
             }
@@ -1189,18 +1195,21 @@ export class CurrentUserUtils {
                 sharedDocs.childContextMenuFilters = new List<ScriptField>([dashboardFilter!,]);
                 sharedDocs.childContextMenuScripts = new List<ScriptField>([addToDashboards!,]);
                 sharedDocs.childContextMenuLabels = new List<string>(["Add to Dashboards",]);
+                sharedDocs.childContextMenuIcons = new List<string>(["user-plus",]);
+
             }
             doc.mySharedDocs = new PrefetchProxy(sharedDocs);
         }
     }
 
     // Import sidebar is where shared documents are contained
-    static setupImportSidebar(doc: Doc) {
-        if (doc.myImportDocs === undefined) {
-            const newUpload = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("importDocument()"), toolTip: "Upload from computer", _width: 100, _stayInCollection: true, _hideContextMenu: true, title: "Upload", btnType: ButtonType.TextButton, buttonText: "Upload from computer", icon: "upload", system: true });
-            doc.myImportDocs = new PrefetchProxy(Docs.Create.StackingDocument([newUpload], {
-                title: "My Uploads", _forceActive: true, ignoreClick: true, _stayInCollection: true, _hideContextMenu: true, childLimitHeight: 0,
-                childDropAction: "alias", _autoHeight: true, _yMargin: 50, _gridGap: 15, boxShadow: "0 0", _lockedPosition: true, system: true, _chromeHidden: true,
+    static setupUploadSidebar(doc: Doc) {
+        if (doc.myUploadDocs === undefined) {
+            const newUploadButton:Doc = Docs.Create.FontIconDocument({ onClick: ScriptField.MakeScript("importDocument()"), _forceActive: true, toolTip: "Upload from computer", _width: 30, _height: 30, _stayInCollection: true, _hideContextMenu: true, title: "Upload", btnType: ButtonType.ClickButton, buttonText: "Upload", icon: "upload", system: true });
+            doc.myUploadDocs = new PrefetchProxy(Docs.Create.StackingDocument([], {
+                title: "My Uploads", _forceActive: true, buttonMenu: true, buttonMenuDoc: newUploadButton, ignoreClick: true, _showTitle: "title", _stayInCollection: true, _hideContextMenu: true, childLimitHeight: 0,
+                childDropAction: "copy", _autoHeight: true, _yMargin: 50, _gridGap: 15, boxShadow: "0 0", _lockedPosition: true, system: true, _chromeHidden: true,
+                explainer: "All of the documents that are imported into Dash will go here and stay here unless they are explicitly removed."
             }));
         }
     }
@@ -1303,7 +1312,7 @@ export class CurrentUserUtils {
         doc.filterDocCount = 0;
         this.setupDefaultIconTemplates(doc);  // creates a set of icon templates triggered by the document deoration icon
         this.setupDocTemplates(doc); // sets up the template menu of templates
-        this.setupImportSidebar(doc); // sets up the import sidebar
+        this.setupUploadSidebar(doc); // sets up the import sidebar
         this.setupSearchSidebar(doc); // sets up the search sidebar
         this.setupActiveMobileMenu(doc); // sets up the current mobile menu for Dash Mobile
         this.setupOverlays(doc);  // documents in overlay layer
@@ -1430,7 +1439,7 @@ export class CurrentUserUtils {
                     }
                 }
             } else if (input.files && input.files.length !== 0) {
-                const importDocs = Cast(Doc.UserDoc().myImportDocs, Doc, null);
+                const importDocs = Cast(Doc.UserDoc().myUploadDocs, Doc, null);
                 const disposer = OverlayView.ShowSpinner();
                 DocListCastAsync(importDocs.data).then(async list => {
                     const results = await DocUtils.uploadFilesToDocs(Array.from(input.files || []), {});
diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss
index 41a6dc569..47ae0424b 100644
--- a/src/client/views/ContextMenu.scss
+++ b/src/client/views/ContextMenu.scss
@@ -130,7 +130,7 @@
 }
 
 .contextMenu-inlineMenu {
-    border-top: solid 1px;
+    // border-top: solid 1px; //TODO:glr clean
 }
 
 .contextMenu-item:hover {
diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx
index 168fcb888..c3921d846 100644
--- a/src/client/views/ContextMenuItem.tsx
+++ b/src/client/views/ContextMenuItem.tsx
@@ -116,12 +116,12 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select
                     style={{ alignItems: where, borderTop: this.props.addDivider ? "solid 1px" : undefined }}
                     onMouseLeave={this.onPointerLeave} onMouseEnter={this.onPointerEnter}>
                     {this.props.icon ? (
-                        <span className="icon-background" onMouseEnter={this.onPointerLeave} style={{ alignItems: "center" }}>
+                        <span className="icon-background" onMouseEnter={this.onPointerLeave} style={{ alignItems: "center", alignSelf: "center" }}>
                             <FontAwesomeIcon icon={this.props.icon} size="sm" />
                         </span>
                     ) : null}
                     <div className="contextMenu-description" onMouseEnter={this.onPointerEnter}
-                        style={{ alignItems: "center" }} >
+                        style={{ alignItems: "center", alignSelf: "center" }} >
                         {this.props.description}
                         <FontAwesomeIcon icon={"angle-right"} size="lg" style={{ position: "absolute", right: "10px" }} />
                     </div>
diff --git a/src/client/views/MainViewModal.scss b/src/client/views/MainViewModal.scss
index 03cb5cc84..0648e31c5 100644
--- a/src/client/views/MainViewModal.scss
+++ b/src/client/views/MainViewModal.scss
@@ -6,6 +6,7 @@
     height: 100%;
 
     .dialogue-box {
+        padding: 10px;
         position: absolute;
         z-index: 1000;
         text-align: center;
@@ -13,7 +14,7 @@
         align-self: center;
         align-content: center;
         background: white;
-        border-radius: 10px;
+        // border-radius: 10px;
         box-shadow: #00000044 5px 5px 10px;
         transform: translate(-50%, -50%);
         top: 50%;
diff --git a/src/client/views/PropertiesButtons.scss b/src/client/views/PropertiesButtons.scss
index 484522bc7..77686a710 100644
--- a/src/client/views/PropertiesButtons.scss
+++ b/src/client/views/PropertiesButtons.scss
@@ -67,10 +67,12 @@ $linkGap : 3px;
 }
 
 .onClickFlyout-editScript {
+    cursor: pointer;
     text-align: center;
-    border: 0.5px solid grey;
+    margin-top: 5px;
+    border: 0.5px solid $medium-gray;
     background-color: rgb(230, 230, 230);
-    border-radius: 9px;
+    border-radius: 5px;
     padding: 4px;
 }
 
@@ -84,9 +86,32 @@ $linkGap : 3px;
     margin-bottom: 8px;
 }
 
+.propertiesButton-dropdownList {
+    width: 100%;
+    height: fit-content;
+    top: 100%;
+    z-index: 21;
+
+    .list-item {
+        cursor: pointer;
+        color: $black;
+        width: 100%;
+        height: 25px;
+        font-weight: 400;
+        display: flex;
+        justify-content: left;
+        align-items: center;
+        padding-left: 5px;
+    }
+
+    .list-item:hover {
+        background-color: lightgrey;
+    }
+}
+
 .propertiesButtons-title {
-    background: #121721;
-    color: white;
+    background: $dark-gray;
+    color: $white;
     font-size: 6px;
     width: 37px;
     padding: 3px;
@@ -111,17 +136,11 @@ $linkGap : 3px;
     margin-left: 4px;
 
     &:hover {
-        background: $medium-gray;
-        transform: scale(1.05);
+        filter:brightness(0.85);
         cursor: pointer;
     }
 }
 
-.propertiesButtons-linker:hover {
-    cursor: pointer;
-    transform: scale(1.05);
-}
-
 
 @-moz-keyframes spin {
     100% {
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index dcab9bc1e..4fde1124f 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -15,6 +15,7 @@ import { InkingStroke } from './InkingStroke';
 import { DocumentView } from './nodes/DocumentView';
 import './PropertiesButtons.scss';
 import React = require("react");
+import { Colors } from "./global/globalEnums";
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -128,11 +129,11 @@ export class PropertiesButtons extends React.Component<{}, {}> {
 
     @undoBatch
     @action
-    handleOptionChange = (e: any) => {
-        this.selectedDoc && (this.selectedDoc.onClickBehavior = e.target.value);
+    handleOptionChange = (onClick: string) => {
+        this.selectedDoc && (this.selectedDoc.onClickBehavior = onClick);
         SelectionManager.Views().filter(dv => dv.docView).map(dv => dv.docView!).forEach(docView => {
             docView.noOnClick();
-            switch (e.target.value) {
+            switch (onClick) {
                 case "enterPortal": docView.makeIntoPortal(); break;
                 case "toggleDetail": docView.setToggleDetail(); break;
                 case "linkInPlace": docView.toggleFollowLink("inPlace", true, false); break;
@@ -149,20 +150,34 @@ export class PropertiesButtons extends React.Component<{}, {}> {
 
     @computed
     get onClickFlyout() {
-        const makeLabel = (value: string, label: string) => <div className="radio">
-            <label>
-                <input type="radio" value={value} checked={(this.selectedDoc?.onClickBehavior ?? "nothing") === value} onChange={this.handleOptionChange} />
-                {label}
-            </label>
-        </div>;
+        const buttonList = [
+            ["nothing", "Select Document"],
+            ["enterPortal", "Enter Portal"],
+            ["toggleDetail", "Toggle Detail"],
+            ["linkInPlace", "Follow Link"],
+            ["linkOnRight", "Open Link on Right"]
+        ]
+        const currentSelection = this.selectedDoc.onClickBehavior;
+        // Get items to place into the list
+
+        const list = buttonList.map((value) => {
+            const click = () => {
+                this.handleOptionChange(value[0]);
+            };
+            return <div className="list-item" key={`${value}`}
+                style={{
+                    backgroundColor: value[0] === currentSelection ? Colors.LIGHT_BLUE : undefined
+                }}
+                onClick={click}>
+                {value[1]}
+            </div>;
+        });
         return <div>
-            <form>
-                {makeLabel("nothing", "Select Document")}
-                {makeLabel("enterPortal", "Enter Portal")}
-                {makeLabel("toggleDetail", "Toggle Detail")}
-                {makeLabel("linkInPlace", "Follow Link")}
-                {makeLabel("linkOnRight", "Open Link on Right")}
-            </form>
+            <div>
+                <div className="propertiesButton-dropdownList">
+                    {list}
+                </div>
+            </div>
             {Doc.UserDoc().noviceMode ? (null) : <div onPointerDown={this.editOnClickScript} className="onClickFlyout-editScript"> Edit onClick Script</div>}
         </div>;
     }
@@ -190,7 +205,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         const isFreeForm = this.selectedDoc?._viewType === CollectionViewType.Freeform;
         const isTree = this.selectedDoc?._viewType === CollectionViewType.Tree;
         const toggle = (ele: JSX.Element | null, style?: React.CSSProperties) => <div className="propertiesButtons-button" style={style}> {ele} </div>;
-
+        const isNovice = Doc.UserDoc().noviceMode;
         return !this.selectedDoc ? (null) :
             <div className="propertiesButtons">
                 {toggle(this.titleButton)}
@@ -198,7 +213,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
                 {toggle(this.lockButton)}
                 {toggle(this.dictationButton)}
                 {toggle(this.onClickButton)}
-                {toggle(this.fitWidthButton)}
+                {toggle(this.fitWidthButton, { display: isNovice ? "none" : "" })}
                 {toggle(this.fitContentButton, { display: !isFreeForm ? "none" : "" })}
                 {toggle(this.autoHeightButton, { display: !isText && !isStacking && !isTree ? "none" : "" })}
                 {toggle(this.maskButton, { display: !isInk ? "none" : "" })}
@@ -207,7 +222,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
                 {toggle(this.snapButton, { display: isCollection ? "" : "none" })}
                 {toggle(this.clustersButton, { display: !isFreeForm ? "none" : "" })}
                 {toggle(this.panButton, { display: !isFreeForm ? "none" : "" })}
-                {toggle(this.perspectiveButton, { display: !isCollection ? "none" : "" })}
+                {toggle(this.perspectiveButton, { display: !isCollection || isNovice ? "none" : "" })}
             </div>;
     }
 }
\ No newline at end of file
diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx
index 0e3663f65..01b79ffd2 100644
--- a/src/client/views/SidebarAnnos.tsx
+++ b/src/client/views/SidebarAnnos.tsx
@@ -106,9 +106,10 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
                 {user}
             </div>;
         };
+        // TODO: Calculation of the topbar is hardcoded and different for text nodes - it should all be the same and all be part of SidebarAnnos
         return !this.props.showSidebar ? (null) :
             <div style={{
-                position: "absolute", pointerEvents: this.props.isContentActive() ? "all" : undefined, top: 0, right: 0,
+                position: "absolute", pointerEvents: this.props.isContentActive() ? "all" : undefined, top: this.props.rootDoc.type !== DocumentType.RTF && StrCast(this.props.rootDoc._showTitle) === "title" ? 15 : 0, right: 0,
                 background: this.props.styleProvider?.(this.props.rootDoc, this.props, StyleProp.WidgetColor),
                 width: `${this.panelWidth()}px`,
                 height: "100%"
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index fa35081bc..e528e84e3 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -89,7 +89,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
     switch (property.split(":")[0]) {
         case StyleProp.TreeViewIcon: return Doc.toIcon(doc, isOpen);
         case StyleProp.DocContents: return undefined;
-        case StyleProp.WidgetColor: return isAnnotated ? "lightBlue" : darkScheme() ? "lightgrey" : "dimgrey";
+        case StyleProp.WidgetColor: return isAnnotated ? Colors.LIGHT_BLUE : darkScheme() ? "lightgrey" : "dimgrey";
         case StyleProp.Opacity: return Cast(doc?._opacity, "number", Cast(doc?.opacity, "number", null));
         case StyleProp.HideLinkButton: return props?.hideLinkButton || (!selected && (doc?.isLinkButton || doc?.hideLinkButton));
         case StyleProp.FontSize: return StrCast(doc?.[fieldKey + "fontSize"]);
@@ -108,7 +108,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
         case StyleProp.TitleHeight: return 15;
         case StyleProp.BorderPath: return comicStyle() && props?.renderDepth ? { path: wavyBorderPath(props?.PanelWidth?.() || 0, props?.PanelHeight?.() || 0), fill: wavyBorderPath(props?.PanelWidth?.() || 0, props?.PanelHeight?.() || 0, .08), width: 3 } : { path: undefined, width: 0 };
         case StyleProp.JitterRotation: return comicStyle() ? random(-1, 1, NumCast(doc?.x), NumCast(doc?.y)) * ((props?.PanelWidth() || 0) > (props?.PanelHeight() || 0) ? 5 : 10) : 0;
-        case StyleProp.HeaderMargin: return ([CollectionViewType.Stacking, CollectionViewType.Masonry].includes(doc?._viewType as any) ||
+        case StyleProp.HeaderMargin: return ([CollectionViewType.Stacking, CollectionViewType.Masonry, CollectionViewType.Tree].includes(doc?._viewType as any) ||
             doc?.type === DocumentType.RTF) && showTitle() && !StrCast(doc?.showTitle).includes(":hover") ? 15 : 0;
         case StyleProp.BackgroundColor: {
             if (MainView.Instance.LastButton === doc) return Colors.LIGHT_GRAY;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 6bdeaf722..6a22acae8 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -338,7 +338,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             {this.renderColors(this._col)}
             <div className="collectionSchema-headerMenu-group">
                 <button onClick={() => { this.deleteColumn(this._col.heading); }}
-                >Delete Column</button>
+                >Hide Column</button>
             </div>
         </div>;
     }
diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss
index 4b123c8b6..2f002736d 100644
--- a/src/client/views/collections/CollectionStackingView.scss
+++ b/src/client/views/collections/CollectionStackingView.scss
@@ -14,6 +14,30 @@
     width: 100%;
 }
 
+// TODO:glr Turn this into a seperate class
+.documentButtonMenu {
+    position: relative;
+    height: fit-content;
+    border-bottom: $standard-border;
+    display: flex;
+    justify-content: center;
+    flex-direction: column;
+    align-items: center;
+    align-content: center;
+    padding: 5px 0 5px 0;
+
+    .documentExplanation {
+        width: 90%;
+        margin: 5px;
+        font-size: 11px;
+        background-color: $light-blue;
+        color: $medium-blue;
+        padding: 10px;
+        border-radius: 10px;
+        border: solid 2px $medium-blue;
+    }
+}
+
 .collectionStackingView,
 .collectionMasonryView {
     height: 100%;
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 4fedda1bd..3c9084f64 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -3,7 +3,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { CursorProperty } from "csstype";
 import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx";
 import { observer } from "mobx-react";
-import { DataSym, Doc, HeightSym, Opt, WidthSym } from "../../../fields/Doc";
+import { DataSym, Doc, HeightSym, Opt, WidthSym, DocListCast } from "../../../fields/Doc";
 import { collectionSchema, documentSchema } from "../../../fields/documentSchemas";
 import { Id } from "../../../fields/FieldSymbols";
 import { List } from "../../../fields/List";
@@ -11,7 +11,7 @@ import { listSpec, makeInterface } from "../../../fields/Schema";
 import { SchemaHeaderField } from "../../../fields/SchemaHeaderField";
 import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Types";
 import { TraceMobx } from "../../../fields/util";
-import { emptyFunction, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, Utils } from "../../../Utils";
+import { emptyFunction, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, Utils, returnTrue, returnEmptyDoclist, returnEmptyFilter } from "../../../Utils";
 import { DocUtils, Docs } from "../../documents/Documents";
 import { DragManager, dropActionType } from "../../util/DragManager";
 import { SnappingManager } from "../../util/SnappingManager";
@@ -23,12 +23,14 @@ import { EditableView } from "../EditableView";
 import { LightboxView } from "../LightboxView";
 import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
 import { DocFocusOptions, DocumentView, DocumentViewProps, ViewAdjustment } from "../nodes/DocumentView";
-import { StyleProp } from "../StyleProvider";
+import { StyleProp, DefaultStyleProvider } from "../StyleProvider";
 import { CollectionMasonryViewFieldRow } from "./CollectionMasonryViewFieldRow";
 import "./CollectionStackingView.scss";
 import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewFieldColumn";
 import { CollectionSubView } from "./CollectionSubView";
 import { CollectionViewType } from "./CollectionView";
+import { FontIconBox } from "../nodes/button/FontIconBox";
+import { CurrentUserUtils } from "../../util/CurrentUserUtils";
 const _global = (window /* browser */ || global /* node */) as any;
 
 type StackingDocument = makeInterface<[typeof collectionSchema, typeof documentSchema]>;
@@ -514,6 +516,47 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
         return sections.map((section, i) => this.isStackingView ? this.sectionStacking(section[0], section[1]) : this.sectionMasonry(section[0], section[1], i === 0));
     }
 
+    @computed get buttonMenu() {
+        const menuDoc:Doc = Cast(this.rootDoc.buttonMenuDoc, Doc, null);
+        // TODO:glr Allow support for multiple buttons
+        if (menuDoc){
+            const width: number = NumCast(menuDoc._width, 30);
+            const height: number = NumCast(menuDoc._height, 30);
+            console.log(menuDoc.title, width, height);
+            return (<div className="buttonMenu-docBtn"
+                style = {{width: width, height: height}}>
+                <DocumentView
+                    Document={menuDoc}
+                    DataDoc={menuDoc}
+                    isContentActive={this.props.isContentActive}
+                    isDocumentActive={returnTrue}
+                    addDocument={this.props.addDocument}
+                    moveDocument={this.props.moveDocument}
+                    addDocTab={this.props.addDocTab}
+                    pinToPres={emptyFunction}
+                    rootSelected={this.props.isSelected}
+                    removeDocument={this.props.removeDocument}
+                    ScreenToLocalTransform={Transform.Identity}
+                    PanelWidth={() => 35}
+                    PanelHeight={() => 35}
+                    renderDepth={this.props.renderDepth}
+                    focus={emptyFunction}
+                    styleProvider={this.props.styleProvider}
+                    layerProvider={this.props.layerProvider}
+                    docViewPath={returnEmptyDoclist}
+                    whenChildContentsActiveChanged={emptyFunction}
+                    bringToFront={emptyFunction}
+                    docFilters={this.props.docFilters}
+                    docRangeFilters={this.props.docRangeFilters}
+                    searchFilterDocs={this.props.searchFilterDocs}
+                    ContainingCollectionView={undefined}
+                    ContainingCollectionDoc={undefined} 
+                />
+            </div>
+            );
+        }
+    }
+
 
     @computed get nativeWidth() { return this.props.NativeWidth?.() ?? Doc.NativeWidth(this.layoutDoc); }
     @computed get nativeHeight() { return this.props.NativeHeight?.() ?? Doc.NativeHeight(this.layoutDoc); }
@@ -529,34 +572,50 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
             SetValue: this.addGroup,
             contents: "+ ADD A GROUP"
         };
+        const buttonMenu = this.rootDoc.buttonMenu;
+        const noviceExplainer = this.rootDoc.explainer;
+        console.log(noviceExplainer);
         return (
-            <div className="collectionStackingMasonry-cont" >
-                <div className={this.isStackingView ? "collectionStackingView" : "collectionMasonryView"}
-                    ref={this.createRef}
-                    style={{
-                        overflowY: this.props.isContentActive() ? "auto" : "hidden",
-                        background: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor),
-                        pointerEvents: this.backgroundEvents ? "all" : undefined
-                    }}
-                    onScroll={action(e => this._scroll = e.currentTarget.scrollTop)}
-                    onDrop={this.onExternalDrop.bind(this)}
-                    onContextMenu={this.onContextMenu}
-                    onWheel={e => this.props.isContentActive(true) && e.stopPropagation()} >
-                    {this.renderedSections}
-                    {!this.showAddAGroup ? (null) :
-                        <div key={`${this.props.Document[Id]}-addGroup`} className="collectionStackingView-addGroupButton"
-                            style={{ width: !this.isStackingView ? "100%" : this.columnWidth / this.numGroupColumns - 10, marginTop: 10 }}>
-                            <EditableView {...editableViewProps} />
-                        </div>}
-                    {/* {this.chromeHidden || !this.props.isSelected() ? (null) :
-                        <Switch
-                            onChange={this.onToggle}
-                            onClick={this.onToggle}
-                            defaultChecked={true}
-                            checkedChildren="edit"
-                            unCheckedChildren="view"
-                        />} */}
-                </div> </div>
+            <>
+                {buttonMenu || noviceExplainer ? <div className="documentButtonMenu">
+                    {buttonMenu ? this.buttonMenu : null}
+                    {Doc.UserDoc().isNovice && noviceExplainer ? 
+                        <div className="documentExplanation">
+                            {noviceExplainer}
+                        </div>
+                        : null
+                    }
+                </div> : null}
+                <div className="collectionStackingMasonry-cont" >
+                    <div className={this.isStackingView ? "collectionStackingView" : "collectionMasonryView"}
+                        ref={this.createRef}
+                        style={{
+                            overflowY: this.props.isContentActive() ? "auto" : "hidden",
+                            background: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor),
+                            pointerEvents: this.backgroundEvents ? "all" : undefined
+                        }}
+                        onScroll={action(e => this._scroll = e.currentTarget.scrollTop)}
+                        onDrop={this.onExternalDrop.bind(this)}
+                        onContextMenu={this.onContextMenu}
+                        onWheel={e => this.props.isContentActive(true) && e.stopPropagation()} >
+                        {this.renderedSections}
+                        {!this.showAddAGroup ? (null) :
+                            <div key={`${this.props.Document[Id]}-addGroup`} className="collectionStackingView-addGroupButton"
+                                style={{ width: !this.isStackingView ? "100%" : this.columnWidth / this.numGroupColumns - 10, marginTop: 10 }}>
+                                <EditableView {...editableViewProps} />
+                            </div>}
+                        {/* {this.chromeHidden || !this.props.isSelected() ? (null) :
+                            <Switch
+                                onChange={this.onToggle}
+                                onClick={this.onToggle}
+                                defaultChecked={true}
+                                checkedChildren="edit"
+                                unCheckedChildren="view"
+                            />} */}
+                    </div> 
+                </div>
+            </>
+            
         );
     }
 }
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 89d42439e..4d62a1af4 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -8,7 +8,7 @@ import { Document, listSpec } from '../../../fields/Schema';
 import { ScriptField } from '../../../fields/ScriptField';
 import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
 import { TraceMobx } from '../../../fields/util';
-import { returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../../Utils';
+import { returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, emptyFunction } from '../../../Utils';
 import { DocUtils } from '../../documents/Documents';
 import { CurrentUserUtils } from '../../util/CurrentUserUtils';
 import { DocumentManager } from '../../util/DocumentManager';
@@ -26,6 +26,7 @@ import { CollectionSubView } from "./CollectionSubView";
 import "./CollectionTreeView.scss";
 import { TreeView } from "./TreeView";
 import React = require("react");
+import { Transform } from '../../util/Transform';
 const _global = (window /* browser */ || global /* node */) as any;
 
 export type collectionTreeViewProps = {
@@ -221,8 +222,9 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
     }
     childContextMenuItems = () => {
         const customScripts = Cast(this.doc.childContextMenuScripts, listSpec(ScriptField), []);
-        const filterScripts = Cast(this.doc.childContextMenuFilters, listSpec(ScriptField), []);
-        return StrListCast(this.doc.childContextMenuLabels).map((label, i) => ({ script: customScripts[i], filter: filterScripts[i], label }));
+        const customFilters = Cast(this.doc.childContextMenuFilters, listSpec(ScriptField), []);
+        const icons = StrListCast(this.doc.childContextMenuIcons);
+        return StrListCast(this.doc.childContextMenuLabels).map((label, i) => ({ script: customScripts[i], filter: customFilters[i], icon: icons[i], label }));
     }
     @computed get treeViewElements() {
         TraceMobx();
@@ -265,13 +267,48 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
         return hideTitle ? (null) : (this.outlineMode ? this.documentTitle : this.editableTitle)(this.treeChildren);
     }
 
-    @computed get renderClearButton() {
-        return !this.doc.treeViewShowClearButton ? (null) : <div key="toolbar">
-            <button className="toolbar-button round-button" title="Empty" onClick={undoBatch(action(() => Doc.GetProto(this.doc)[this.props.fieldKey] = undefined))}>
-                <FontAwesomeIcon icon={"trash"} size="sm" />
-            </button>
-        </div >;
+    @computed get buttonMenu() {
+        const menuDoc:Doc = Cast(this.rootDoc.buttonMenuDoc, Doc, null);
+        // To create a multibutton menu add a CollectionLinearView
+        if (menuDoc){
+            
+            const width: number = NumCast(menuDoc._width, 30);
+            const height: number = NumCast(menuDoc._height, 30);
+            console.log(menuDoc.title, width, height);
+            return (<div className="buttonMenu-docBtn"
+                style = {{width: width, height: height}}>
+                <DocumentView
+                    Document={menuDoc}
+                    DataDoc={menuDoc}
+                    isContentActive={this.props.isContentActive}
+                    isDocumentActive={returnTrue}
+                    addDocument={this.props.addDocument}
+                    moveDocument={this.props.moveDocument}
+                    addDocTab={this.props.addDocTab}
+                    pinToPres={emptyFunction}
+                    rootSelected={this.props.isSelected}
+                    removeDocument={this.props.removeDocument}
+                    ScreenToLocalTransform={Transform.Identity}
+                    PanelWidth={() => 35}
+                    PanelHeight={() => 35}
+                    renderDepth={this.props.renderDepth + 1}
+                    focus={emptyFunction}
+                    styleProvider={this.props.styleProvider}
+                    layerProvider={this.props.layerProvider}
+                    docViewPath={returnEmptyDoclist}
+                    whenChildContentsActiveChanged={emptyFunction}
+                    bringToFront={emptyFunction}
+                    docFilters={this.props.docFilters}
+                    docRangeFilters={this.props.docRangeFilters}
+                    searchFilterDocs={this.props.searchFilterDocs}
+                    ContainingCollectionView={undefined}
+                    ContainingCollectionDoc={undefined} 
+                />
+            </div>);
+        }
     }
+
+    
     @computed get nativeWidth() { return Doc.NativeWidth(this.Document, undefined, true); }
     @computed get nativeHeight() { return Doc.NativeHeight(this.Document, undefined, true); }
 
@@ -295,22 +332,34 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
         TraceMobx();
         const background = () => this.props.styleProvider?.(this.doc, this.props, StyleProp.BackgroundColor);
         const pointerEvents = () => !this.props.isContentActive() && !SnappingManager.GetIsDragging() ? "none" : undefined;
+        const buttonMenu = this.rootDoc.buttonMenu;
+        const noviceExplainer = this.rootDoc.explainer;
 
         return !(this.doc instanceof Doc) || !this.treeChildren ? (null) :
-            <div className="collectionTreeView-container"
-                style={this.outlineMode ? { transform: `scale(${this.contentScaling})`, width: `calc(${100 / this.contentScaling}%)` } : {}}
-                onContextMenu={this.onContextMenu}>
-                <div className="collectionTreeView-dropTarget"
-                    style={{ background: background(), paddingLeft: `${this.paddingX()}px`, paddingRight: `${this.paddingX()}px`, paddingBottom: `${this.paddingBot()}px`, paddingTop: `${this.paddingTop()}px`, pointerEvents: pointerEvents() }}
-                    onWheel={e => e.stopPropagation()}
-                    onDrop={this.onTreeDrop}
-                    ref={this.createTreeDropTarget}>
+               <>
                     {this.titleBar}
-                    {this.renderClearButton}
-                    <ul className={`no-indent${this.outlineMode ? "-outline" : ""}`} >
-                        {this.treeViewElements}
-                    </ul>
-                </div >
-            </div>;
+                    <div className="collectionTreeView-container"
+                        style={this.outlineMode ? { transform: `scale(${this.contentScaling})`, width: `calc(${100 / this.contentScaling}%)` } : {}}
+                        onContextMenu={this.onContextMenu}>
+                        {buttonMenu || noviceExplainer ? <div className="documentButtonMenu">
+                            {buttonMenu ? this.buttonMenu : null}
+                            {Doc.UserDoc().noviceMode && noviceExplainer ? 
+                                <div className="documentExplanation">
+                                    {noviceExplainer}
+                                </div>
+                                : null
+                            }
+                        </div> : null}
+                        <div className="collectionTreeView-dropTarget"
+                            style={{ background: background(), paddingLeft: `${this.paddingX()}px`, paddingRight: `${this.paddingX()}px`, paddingBottom: `${this.paddingBot()}px`, paddingTop: `${this.paddingTop()}px`, pointerEvents: pointerEvents() }}
+                            onWheel={e => e.stopPropagation()}
+                            onDrop={this.onTreeDrop}
+                            ref={this.createTreeDropTarget}>
+                            <ul className={`no-indent${this.outlineMode ? "-outline" : ""}`} >
+                                {this.treeViewElements}
+                            </ul>
+                        </div >
+                    </div>
+               </>;
     }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 889db1ef6..34cb6ec55 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -387,9 +387,10 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                     background={this.miniMapColor}
                     document={this._document}
                     tabView={this.tabView} />
-                <Tooltip style={{ display: this.disableMinimap() ? "none" : undefined }} key="ttip" title={<div className="dash-tooltip">{this._document.hideMinimap ? "Open minimap" : "Close minimap"}</div>}>
+                <Tooltip key="ttip" title={<div className="dash-tooltip">{this._document.hideMinimap ? "Open minimap" : "Close minimap"}</div>}>
                     <div className="miniMap-hidden"
                         style={{
+                            display: this.disableMinimap() || this._document._viewType !== "freeform" ? "none" : undefined,
                             color: this._document.hideMinimap ? Colors.BLACK : Colors.WHITE,
                             backgroundColor: this._document.hideMinimap ? Colors.LIGHT_GRAY : Colors.MEDIUM_BLUE,
                             boxShadow: this._document.hideMinimap ? Shadows.STANDARD_SHADOW : undefined
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index b9487054b..8cf34ddcc 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -525,7 +525,8 @@ export class TreeView extends React.Component<TreeViewProps> {
     childContextMenuItems = () => {
         const customScripts = Cast(this.doc.childContextMenuScripts, listSpec(ScriptField), []);
         const customFilters = Cast(this.doc.childContextMenuFilters, listSpec(ScriptField), []);
-        return StrListCast(this.doc.childContextMenuLabels).map((label, i) => ({ script: customScripts[i], filter: customFilters[i], label }));
+        const icons = StrListCast(this.doc.childContextMenuIcons);
+        return StrListCast(this.doc.childContextMenuLabels).map((label, i) => ({ script: customScripts[i], filter: customFilters[i], icon: icons[i], label }));
     }
     onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.treeChildClick));
 
@@ -835,7 +836,7 @@ export class TreeView extends React.Component<TreeViewProps> {
         dontRegisterView: boolean | undefined,
         observerHeight: (ref: any) => void,
         unobserveHeight: (ref: any) => void,
-        contextMenuItems: ({ script: ScriptField, filter: ScriptField, label: string }[])
+        contextMenuItems: ({ script: ScriptField, filter: ScriptField, label: string, icon: string }[])
     ) {
         const viewSpecScript = Cast(conainerCollection.viewSpecScript, ScriptField);
         if (viewSpecScript) {
diff --git a/src/client/views/collections/collectionLinearView/CollectionLinearView.scss b/src/client/views/collections/collectionLinearView/CollectionLinearView.scss
index f249eb1f5..8fe804466 100644
--- a/src/client/views/collections/collectionLinearView/CollectionLinearView.scss
+++ b/src/client/views/collections/collectionLinearView/CollectionLinearView.scss
@@ -98,7 +98,11 @@
             transition: transform 0.2s;
             align-items: center;
             justify-content: center;
-            transition: 0.15s;
+            transition: 0.2s;
+
+            &:hover{
+                filter: brightness(0.85);
+            }
         }
 
         >input {
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx
index b28c32e0e..a25f962df 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx
@@ -191,7 +191,7 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
                         {this.renderSorting()}
                         {this.renderColors()}
                         <div className="collectionSchema-headerMenu-group">
-                            <button onClick={() => this.props.deleteColumn(this.props.columnField.heading)}>Delete Column</button>
+                            <button onClick={() => this.props.deleteColumn(this.props.columnField.heading)}>Hide Column</button>
                         </div>
                     </>
                 }
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index fed64b620..dfe99ffc8 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -338,7 +338,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             {this.renderColors(this._col)}
             <div className="collectionSchema-headerMenu-group">
                 <button onClick={() => { this.deleteColumn(this._col.heading); }}
-                >Delete Column</button>
+                >Hide Column</button>
             </div>
         </div>;
     }
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index f5a7e61aa..8962d29f0 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -638,12 +638,12 @@ export class AudioBox extends ViewBoxAnnotatableComponent<
                                 </div>
                             </div>
                         ) : (
-                                <button
+                                <div
                                     className={`audiobox-record${interactive}`}
                                     style={{ backgroundColor: Colors.DARK_GRAY }}
                                 >
                                     RECORD
-                                </button>
+                                </div>
                             )}
                     </div>
                 ) : (
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 7463e192f..98ae279db 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -635,7 +635,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
     makeIntoPortal = async () => {
         const portalLink = this.allLinks.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), _fitWidth: true, title: StrCast(this.props.Document.title) + ".portal" });
+            const portal = Docs.Create.FreeformDocument([], { _width: NumCast(this.layoutDoc._width) + 10, _height: NumCast(this.layoutDoc._height), _fitWidth: true, title: StrCast(this.props.Document.title) + " [Portal]" });
             DocUtils.MakeLink({ doc: this.props.Document }, { doc: portal }, "portal to");
         }
         this.Document.followLinkLocation = "inPlace";
@@ -679,7 +679,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             const appearance = cm.findByDescription("UI Controls...");
             const appearanceItems: ContextMenuProps[] = appearance && "subitems" in appearance ? appearance.subitems : [];
             !Doc.UserDoc().noviceMode && templateDoc && appearanceItems.push({ description: "Open Template   ", event: () => this.props.addDocTab(templateDoc, "add:right"), icon: "eye" });
-            appearanceItems.push({
+            !Doc.UserDoc().noviceMode && appearanceItems.push({
                 description: "Add a Field", event: () => {
                     const alias = Doc.MakeAlias(this.rootDoc);
                     alias.layout = FormattedTextBox.LayoutString("newfield");
diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss
index 72dec6e4c..f44355929 100644
--- a/src/client/views/nodes/PDFBox.scss
+++ b/src/client/views/nodes/PDFBox.scss
@@ -1,3 +1,5 @@
+@import "../global/globalCssVariables.scss";
+
 .pdfBox,
 .pdfBox-interactive {
     display: inline-block;
@@ -18,12 +20,13 @@
         top: 0;
         left: 0;
 
+        // glr: This should really be the same component as text and PDFs
         .pdfBox-sidebarBtn {
-            background: #121721;
+            background: $black;
             height: 25px;
             width: 25px;
-            right: 0;
-            color: white;
+            right: 5px;
+            color: $white;
             display: flex;
             position: absolute;
             align-items: center;
@@ -31,6 +34,13 @@
             border-radius: 3px;
             pointer-events: all;
             z-index: 1; // so it appears on top of the document's title, if shown
+
+            box-shadow: $standard-box-shadow;
+            transition: 0.2s;
+
+            &:hover{
+                filter: brightness(0.85);
+            }
         }
 
         .pdfBox-pageNums {
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 5e07229c1..3a399bfdb 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -24,6 +24,7 @@ import { pageSchema } from "./ImageBox";
 import "./PDFBox.scss";
 import React = require("react");
 import { AnchorMenu } from '../pdf/AnchorMenu';
+import { Colors } from '../global/globalEnums';
 
 type PdfDocument = makeInterface<[typeof documentSchema, typeof panZoomSchema, typeof pageSchema]>;
 const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema);
@@ -208,11 +209,15 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                         onClick={action(() => this._pageControls = !this._pageControls)} />
                     {this._pageControls ? pageBtns : (null)}
                 </div>
-                <button className="pdfBox-sidebarBtn" title="Toggle Sidebar"
-                    style={{ display: !this.props.isContentActive() ? "none" : undefined }}
+                <div className="pdfBox-sidebarBtn" key="sidebar" title="Toggle Sidebar"
+                    style={{ 
+                        display: !this.props.isContentActive() ? "none" : undefined, 
+                        top: StrCast(this.rootDoc._showTitle) === "title" ? 20 : 5,
+                        backgroundColor: this.SidebarShown ? Colors.MEDIUM_BLUE : Colors.BLACK
+                    }}
                     onPointerDown={this.sidebarBtnDown} >
-                    <FontAwesomeIcon icon={"chevron-left"} size="sm" />
-                </button>
+                        <FontAwesomeIcon style={{ color: Colors.WHITE }} icon={"comment-alt"} size="sm" />
+                </div>
             </div>;
     }
     sidebarWidth = () => !this.SidebarShown ? 0 :
diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss
index 19b69ff5a..417a17d96 100644
--- a/src/client/views/nodes/WebBox.scss
+++ b/src/client/views/nodes/WebBox.scss
@@ -10,7 +10,7 @@
         background: #121721;
         height: 25px;
         width: 25px;
-        right: 0;
+        right: 5px;
         display: flex;
         position: absolute;
         align-items: center;
@@ -18,6 +18,13 @@
         border-radius: 3px;
         pointer-events: all;
         z-index: 1; // so it appears on top of the document's title, if shown
+
+        box-shadow: $standard-box-shadow;
+        transition: 0.2s;
+
+        &:hover{
+            filter: brightness(0.85);
+        }
     }
 
     .pdfViewerDash-dragAnnotationBox {
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 719e5a796..1f85219d6 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -33,6 +33,7 @@ import { FieldView, FieldViewProps } from './FieldView';
 import { LinkDocPreview } from "./LinkDocPreview";
 import "./WebBox.scss";
 import React = require("react");
+import { Colors } from "../global/globalEnums";
 const _global = (window /* browser */ || global /* node */) as any;
 const htmlToText = require("html-to-text");
 
@@ -590,11 +591,15 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                     moveDocument={this.moveDocument}
                     removeDocument={this.removeDocument}
                 />
-                <button className="webBox-overlayButton-sidebar" key="sidebar" title="Toggle Sidebar"
-                    style={{ display: !this.props.isContentActive() ? "none" : undefined }}
+                <div className="webBox-overlayButton-sidebar" key="sidebar" title="Toggle Sidebar"
+                    style={{ 
+                        display: !this.props.isContentActive() ? "none" : undefined, 
+                        top: StrCast(this.rootDoc._showTitle) === "title" ? 20 : 5,
+                        backgroundColor: this.SidebarShown ? Colors.MEDIUM_BLUE : Colors.BLACK
+                    }}
                     onPointerDown={this.sidebarBtnDown} >
-                    <FontAwesomeIcon style={{ color: "white" }} icon={"chevron-left"} size="sm" />
-                </button>
+                        <FontAwesomeIcon style={{ color: Colors.WHITE }} icon={"comment-alt"} size="sm" />
+                </div>
             </div>);
     }
 }
diff --git a/src/client/views/nodes/button/FontIconBox.scss b/src/client/views/nodes/button/FontIconBox.scss
index 48fb2c8dc..a2da35fe1 100644
--- a/src/client/views/nodes/button/FontIconBox.scss
+++ b/src/client/views/nodes/button/FontIconBox.scss
@@ -7,6 +7,7 @@
     align-items: center;
     font-size: 80%;
     border-radius: $standard-border-radius;
+    transition: 0.15s;
 
     .menuButton-wrap {
         grid-column: 1;
@@ -29,6 +30,9 @@
         font-family: 'ROBOTO';
         text-transform: uppercase;
         font-weight: bold;
+        transition: 0.15s;
+
+
     }
 
     .fontIconBox-icon {
@@ -50,7 +54,18 @@
     }
 
     &.textBtn {
+        display: grid;
+        /* grid-row: auto; */
+        grid-auto-flow: column;
+        cursor: pointer;
         width: 100%;
+        justify-content: center;
+        align-items: center;
+        justify-items: center;
+
+        &:hover {
+            filter:brightness(0.85) !important;
+        }
     }
 
     &.tglBtn {
@@ -127,13 +142,13 @@
         }
 
         &:hover {
-            background-color: rgba(0, 0, 0, 0.3) !important;
+            background-color: rgba(0, 0, 0, 0.3);
         }
     }
 
     &.toolBtn {
         cursor: pointer;
-        width: 40px;
+        width: 100%;
         border-radius: 100%;
 
         svg {
@@ -143,7 +158,7 @@
     }
 
     &.menuBtn {
-        cursor: pointer;
+        cursor: pointer !important;
         border-radius: 0px;
         flex-direction: column;
 
@@ -151,6 +166,10 @@
             width: 45% !important;
             height: 45%;
         }
+        
+        &:hover{
+            filter: brightness(0.85);
+        }
     }
 
 
@@ -163,8 +182,8 @@
 
         .colorButton-color {
             margin-top: 3px;
-            width: 90%;
-            height: 6px;
+            width: 80%;
+            height: 3px;
         }
 
         .menuButton-dropdownBox {
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index bccf733f0..1b27d562a 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -253,11 +253,12 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
             } else if (selected) {
                 dropdown = false;
                 text = StrCast(selected.Document.type);
+                if (text === DocumentType.RTF) text = "Text";
                 icon = Doc.toIcon(selected.Document);
             } else {
                 dropdown = false;
-                noneSelected = true;
-                text = "None selected";
+                icon = "globe-asia";
+                text = "User Default";
             }
             noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking];
         } else if (script === 'setFont') {
@@ -302,7 +303,7 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
             <div className={`menuButton ${this.type} ${active}`}
                 style={{ backgroundColor: this.rootDoc.dropDownOpen ? Colors.MEDIUM_BLUE : backgroundColor, color: color, display: dropdown ? undefined : "flex" }}
                 onClick={dropdown ? () => this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen : undefined}>
-                {dropdown || noneSelected ? (null) : <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />}
+                {dropdown || noneSelected ? (null) : <FontAwesomeIcon style={{marginLeft: 5}} className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />}
                 <div className="menuButton-dropdown-header">
                     {text && text[0].toUpperCase() + text.slice(1)}
                 </div>
@@ -487,7 +488,7 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
             </div>;
 
         const menuLabel = !this.label || !Doc.UserDoc()._showMenuLabel ? (null) :
-            <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor }}>
+            <div className="fontIconBox-label" style={{ color: color, backgroundColor: "transparent" }}>
                 {this.label}
             </div>;
 
@@ -508,7 +509,7 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
         switch (this.type) {
             case ButtonType.TextButton:
                 button = (
-                    <div className={`menuButton ${this.type}`} style={{ color: color, backgroundColor: backgroundColor, opacity: 1 }}>
+                    <div className={`menuButton ${this.type}`} style={{ color: color, backgroundColor: backgroundColor, opacity: 1, gridAutoColumns: `${NumCast(this.rootDoc._height)} auto` }}>
                         <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />
                         {buttonText ? 
                             <div className="button-text">
@@ -558,7 +559,7 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
                 break;
             case ButtonType.MenuButton:
                 const trailsIcon = <img src={`/assets/${"presTrails.png"}`}
-                    style={{ width: 20, height: 20, filter: `invert(${color === Colors.DARK_GRAY ? "0%" : "100%"})` }} />;
+                    style={{ width: 30, height: 30, filter: `invert(${color === Colors.DARK_GRAY ? "0%" : "100%"})` }} />;
                 button = (
                     <div className={`menuButton ${this.type}`} style={{ color: color, backgroundColor: backgroundColor }}>
                         {this.icon === "pres-trail" ? trailsIcon : <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={this.icon} color={color} />}
@@ -605,7 +606,7 @@ Scripting.addGlobal(function setBackgroundColor(color?: string, checkResult?: bo
 Scripting.addGlobal(function toggleOverlay(checkResult?: boolean) {
     const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
     if (checkResult && selected) {
-        if (NumCast(selected.Document.z) === 1) return Colors.MEDIUM_BLUE;
+        if (NumCast(selected.Document.z) >= 1) return Colors.MEDIUM_BLUE;
         else return "transparent";
     }
     selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log("[FontIconBox.tsx] toggleOverlay failed");
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.scss b/src/client/views/nodes/formattedText/FormattedTextBox.scss
index 3cedab1a4..56f5c5631 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.scss
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.scss
@@ -66,14 +66,25 @@ audiotag:hover {
     
 .formattedTextBox-sidebar-handle {
     position: absolute;
-    top: 0;
+    top: 5px;
     //top: calc(50% - 17.5px);  // use this to center vertically -- make sure it looks okay for slide views
-    width: 10px;
+    width: 25px;
     height: 100%;
-    max-height: 35px;
-    background: lightgray;
-    border-radius: 20px;
+    max-height: 25px;
+    color: white;
+    background: $medium-gray;
+    border-radius: 5px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
     cursor:grabbing;
+    box-shadow: $standard-box-shadow;
+    // transition: 0.2s;
+
+    &:hover{
+        filter: brightness(0.85);
+    }
+
 }
 
 .formattedTextBox-sidebar,
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index f45b9de7a..468edf6cc 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -63,6 +63,8 @@ import { SummaryView } from "./SummaryView";
 import applyDevTools = require("prosemirror-dev-tools");
 import React = require("react");
 import { SidebarAnnos } from '../../SidebarAnnos';
+import { Colors } from '../../global/globalEnums';
+import { IconProp } from '@fortawesome/fontawesome-svg-core';
 const translateGoogleApi = require("translate-google-api");
 
 export interface FormattedTextBoxProps {
@@ -574,11 +576,12 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
         changeItems.push({ description: "plain", event: undoBatch(() => Doc.setNativeView(this.rootDoc)), icon: "eye" });
         const noteTypesDoc = Cast(Doc.UserDoc()["template-notes"], Doc, null);
         DocListCast(noteTypesDoc?.data).forEach(note => {
+            const icon: IconProp = StrCast(note.icon) as IconProp;
             changeItems.push({
                 description: StrCast(note.title), event: undoBatch(() => {
                     Doc.setNativeView(this.rootDoc);
                     DocUtils.makeCustomViewClicked(this.rootDoc, Docs.Create.TreeDocument, StrCast(note.title), note);
-                }), icon: "eye"
+                }), icon: icon
             });
         });
         !Doc.UserDoc().noviceMode && changeItems.push({ description: "FreeForm", event: () => DocUtils.makeCustomViewClicked(this.rootDoc, Docs.Create.FreeformDocument, "freeform"), icon: "eye" });
@@ -1481,11 +1484,16 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
     @computed get sidebarHandle() {
         TraceMobx();
         const annotated = DocListCast(this.dataDoc[this.SidebarKey]).filter(d => d?.author).length;
+        const color = !annotated ? Colors.WHITE : Colors.BLACK;
+        const backgroundColor = !annotated ? this.sidebarWidth() ? Colors.MEDIUM_BLUE : Colors.BLACK : this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.WidgetColor + (annotated ? ":annotated" : ""));
         return (!annotated && !this.props.isContentActive()) ? (null) : <div className="formattedTextBox-sidebar-handle" onPointerDown={this.sidebarDown}
             style={{
-                left: `max(0px, calc(100% - ${this.sidebarWidthPercent} ${this.sidebarWidth() ? "- 5px" : "- 10px"}))`,
-                background: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.WidgetColor + (annotated ? ":annotated" : ""))
-            }} />;
+                left: `max(0px, calc(100% - ${this.sidebarWidthPercent} ${"- 30px"}))`,
+                backgroundColor: backgroundColor,
+                color: color
+            }} >
+                <FontAwesomeIcon icon={"comment-alt"}/>
+            </div>;
     }
     @computed get sidebarCollection() {
         const renderComponent = (tag: string) => {
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index 260ddfc90..e70b2bc19 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -114,7 +114,7 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps, SearchBoxDoc
             const linkFrom = this.props.linkFrom();
             if (linkFrom) {
                 console.log(linkFrom.title);
-                DocUtils.MakeLink({ doc: linkFrom }, { doc: linkTo });
+                DocUtils.MakeLink({ doc: linkFrom }, { doc: linkTo }, "Link");
             }
         }
     });
diff --git a/src/client/views/topbar/TopBar.scss b/src/client/views/topbar/TopBar.scss
index 05aeb177c..923f1892e 100644
--- a/src/client/views/topbar/TopBar.scss
+++ b/src/client/views/topbar/TopBar.scss
@@ -33,12 +33,12 @@
             align-self: center;
             border-radius: $standard-border-radius;
             padding: 5px;
-            transition: linear 0.1s;
+            transition: linear 0.2s;
             color: $black;
             background-color: $light-gray;
 
             &:hover {
-                background-color: $light-blue;
+                background-color: darken($color: $light-gray, $amount: 20);
             }
         }
 
diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx
index 4dbd5e22c..d5254e315 100644
--- a/src/client/views/topbar/TopBar.tsx
+++ b/src/client/views/topbar/TopBar.tsx
@@ -51,7 +51,8 @@ export class TopBar extends React.Component {
                         </div>
                     </div>
                     <div className="topbar-right" >
-                        <div className="topbar-icon">
+                        <div className="topbar-icon" onClick={() => window.open(
+                            "https://brown-dash.github.io/Dash-Documentation/", "_blank")}>
                             {"Help"}<FontAwesomeIcon icon="question-circle"></FontAwesomeIcon>
                         </div>
                         <div className="topbar-icon" onClick={() => SettingsManager.Instance.open()}>
-- 
cgit v1.2.3-70-g09d2


From 42d98f5c0a35e173e5eb4651a9a48567a209550f Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 10 Sep 2021 13:53:35 -0400
Subject: made web page menu UI functional.  made ink show up in minmimap.

---
 src/client/util/CurrentUserUtils.ts           |  4 ++--
 src/client/views/EditableView.scss            |  1 +
 src/client/views/EditableView.tsx             |  4 ++--
 src/client/views/collections/TabDocView.tsx   |  2 +-
 src/client/views/nodes/button/FontIconBox.tsx | 30 ++++++++++++++++++++-------
 5 files changed, 28 insertions(+), 13 deletions(-)

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

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index d58917704..d71537e75 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -1026,8 +1026,8 @@ export class CurrentUserUtils {
             [
                 { title: "Back", toolTip: "Go back", btnType: ButtonType.ClickButton, icon: "arrow-left", click: 'webBack()' },
                 { title: "Forward", toolTip: "Go forward", btnType: ButtonType.ClickButton, icon: "arrow-right", click: 'webForward()' },
-                { title: "Reload", toolTip: "Reload webpage", btnType: ButtonType.ClickButton, icon: "redo-alt", click: 'webReload()' },
-                { title: "URL", toolTip: "URL", width: 150, btnType: ButtonType.EditableText, icon: "lock", ignoreClick: true, script: 'webSetURL' },
+                //{ title: "Reload", toolTip: "Reload webpage", btnType: ButtonType.ClickButton, icon: "redo-alt", click: 'webReload()' },
+                { title: "URL", toolTip: "URL", width: 250, btnType: ButtonType.EditableText, icon: "lock", ignoreClick: true, script: 'webSetURL' },
             ];
 
         return tools;
diff --git a/src/client/views/EditableView.scss b/src/client/views/EditableView.scss
index 1aebedf2e..ed7ec9dc1 100644
--- a/src/client/views/EditableView.scss
+++ b/src/client/views/EditableView.scss
@@ -5,6 +5,7 @@
     hyphens: auto;
     overflow: hidden;
     min-width: 20;
+    text-overflow: ellipsis;
 }
 
 .editableView-container-editing-oneLine {
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 83336c180..ebf5ca82d 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -155,7 +155,7 @@ export class EditableView extends React.Component<EditableProps> {
         return wasFocused !== this._editing;
     }
 
-    
+
 
     renderEditor() {
         console.log("render editor", this.props.autosuggestProps);
@@ -200,7 +200,7 @@ export class EditableView extends React.Component<EditableProps> {
         setTimeout(() => this.props.autosuggestProps?.resetValue());
         return this.props.contents instanceof ObjectField ? (null) :
             <div className={`editableView-container-editing${this.props.oneLine ? "-oneLine" : ""}`} ref={this._ref}
-                style={{ display: this.props.display, textOverflow: this.props.overflow, minHeight: "17px", whiteSpace: "nowrap", height: this.props.height || "auto", maxHeight: this.props.maxHeight }}
+                style={{ display: this.props.display, textOverflow: this.props.overflow, minHeight: "10px", whiteSpace: "nowrap", 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 }} >
                     {this.props.contents ? this.props.contents?.valueOf() : this.props.placeholder?.valueOf()}
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 34cb6ec55..f63e5f844 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -439,7 +439,7 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
                 case StyleProp.DocContents:
                     const background = doc.type === DocumentType.PDF ? "red" : doc.type === DocumentType.IMG ? "blue" : doc.type === DocumentType.RTF ? "orange" :
                         doc.type === DocumentType.VID ? "purple" : doc.type === DocumentType.WEB ? "yellow" : "gray";
-                    return doc.type === DocumentType.COL ?
+                    return doc.type === DocumentType.COL || doc.type === DocumentType.INK ?
                         undefined :
                         <div style={{ width: doc[WidthSym](), height: doc[HeightSym](), position: "absolute", display: "block", background }} />;
             }
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index df7c54f67..fefaadc17 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -32,6 +32,7 @@ import { IButtonProps } from './ButtonInterface';
 import { FontIconBadge } from './FontIconBadge';
 import './FontIconBox.scss';
 import { undo } from 'prosemirror-history';
+import { WebBox } from '../WebBox';
 const FontIconSchema = createSchema({
     icon: "string",
 });
@@ -468,8 +469,9 @@ export class FontIconBox extends DocComponent<ButtonProps, FontIconDocument>(Fon
         return (
             <div className="menuButton editableText">
                 <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={"lock"} />
-                <EditableView GetValue={() => checkResult} SetValue={setValue} contents="...">
-                </EditableView>
+                <div style={{ width: "calc(100% - .875em)", paddingLeft: "4px" }}>
+                    <EditableView GetValue={() => checkResult} SetValue={setValue} contents={checkResult} />
+                </div>
             </div>
         );
     }
@@ -869,13 +871,25 @@ Scripting.addGlobal(function setStrokeColor(color?: string, checkResult?: boolea
  *      webSetURL
  **/
 Scripting.addGlobal(function webSetURL(url: string, checkResult?: boolean) {
-    const selected = SelectionManager.Docs().lastElement();
-    console.log("URL: ", url);
-    if (checkResult && selected && selected.type === DocumentType.WEB) {
-        return Cast(selected.data, WebField, null).url;
+    const selected = SelectionManager.Views().lastElement();
+    if (selected?.rootDoc.type === DocumentType.WEB) {
+        if (checkResult) {
+            return StrCast(selected.rootDoc.data, Cast(selected.rootDoc.data, WebField, null)?.url?.href);
+        }
+        (selected.ComponentView as WebBox).submitURL(url);
+        //selected.rootDoc.data = new WebField(url);
     }
-    else if (selected && selected.type === DocumentType.WEB) {
-        selected.data = url;
+});
+Scripting.addGlobal(function webForward() {
+    const selected = SelectionManager.Views().lastElement();
+    if (selected?.rootDoc.type === DocumentType.WEB) {
+        (selected.ComponentView as WebBox).forward();
+    }
+});
+Scripting.addGlobal(function webBack() {
+    const selected = SelectionManager.Views().lastElement();
+    if (selected?.rootDoc.type === DocumentType.WEB) {
+        (selected.ComponentView as WebBox).back();
     }
 });
 
-- 
cgit v1.2.3-70-g09d2


From 643df77e6366b7164307ffe195ed9de83b68e5ae Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 24 Sep 2021 01:21:38 -0400
Subject: wrapped Color() calls in DashColor() to catch exceptions for color
 strings no found

---
 src/Utils.ts                                                  | 11 ++++++++++-
 src/client/views/StyleProvider.tsx                            |  5 ++---
 src/client/views/collections/TabDocView.tsx                   |  3 +--
 .../collections/collectionFreeForm/CollectionFreeFormView.tsx |  1 -
 src/client/views/nodes/CollectionFreeFormDocumentView.tsx     |  5 ++---
 src/client/views/nodes/trails/PresBox.tsx                     |  3 +--
 src/fields/Doc.ts                                             |  9 ++++-----
 src/fields/RichTextUtils.ts                                   |  4 ++--
 8 files changed, 22 insertions(+), 19 deletions(-)

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

diff --git a/src/Utils.ts b/src/Utils.ts
index db33875ea..7ec4f69f3 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -573,10 +573,19 @@ export function simulateMouseClick(element: Element | null | undefined, x: numbe
     }
 }
 
+export function DashColor(color: string) {
+    try {
+        return Color(color.toLowerCase());
+    } catch (e) {
+        console.log("COLOR error:", e);
+        return Color("red");
+    }
+}
+
 export function lightOrDark(color: any) {
     const nonAlphaColor = color.startsWith("#") ? (color as string).substring(0, 7) :
         color.startsWith("rgba") ? color.replace(/,.[^,]*\)/, ")").replace("rgba", "rgb") : color;
-    const col = Color(nonAlphaColor.toLowerCase()).rgb();
+    const col = DashColor(nonAlphaColor).rgb();
     const colsum = (col.red() + col.green() + col.blue());
     if (colsum / col.alpha() > 400 || col.alpha() < 0.25) return Colors.DARK_GRAY;
     else return Colors.WHITE;
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 507c3d2b2..cd6e11bda 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -7,7 +7,7 @@ import { Doc, Opt, StrListCast } from "../../fields/Doc";
 import { List } from '../../fields/List';
 import { listSpec } from '../../fields/Schema';
 import { BoolCast, Cast, NumCast, StrCast } from "../../fields/Types";
-import { lightOrDark } from '../../Utils';
+import { lightOrDark, DashColor } from '../../Utils';
 import { DocumentType } from '../documents/DocumentTypes';
 import { CurrentUserUtils } from '../util/CurrentUserUtils';
 import { ColorScheme } from '../util/SettingsManager';
@@ -21,7 +21,6 @@ import { FieldViewProps } from './nodes/FieldView';
 import { SliderBox } from './nodes/SliderBox';
 import "./StyleProvider.scss";
 import React = require("react");
-import Color = require('color');
 
 export enum StyleLayers {
     Background = "background"
@@ -148,7 +147,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
                 //if (doc._viewType !== CollectionViewType.Freeform && doc._viewType !== CollectionViewType.Time) return "rgb(62,62,62)";
                 default: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.WHITE); break;
             }
-            if (docColor && (!doc || props?.layerProvider?.(doc) === false)) docColor = Color(docColor.toLowerCase()).fade(0.5).toString();
+            if (docColor && (!doc || props?.layerProvider?.(doc) === false)) docColor = DashColor(docColor).fade(0.5).toString();
             return docColor;
         }
         case StyleProp.BoxShadow: {
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index f63e5f844..eb95bb913 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -22,6 +22,7 @@ import { SelectionManager } from '../../util/SelectionManager';
 import { SnappingManager } from '../../util/SnappingManager';
 import { Transform } from '../../util/Transform';
 import { undoBatch, UndoManager } from "../../util/UndoManager";
+import { Colors, Shadows } from '../global/globalEnums';
 import { LightboxView } from '../LightboxView';
 import { DocFocusOptions, DocumentView, DocumentViewProps } from "../nodes/DocumentView";
 import { PinProps, PresBox, PresMovement } from '../nodes/trails';
@@ -32,8 +33,6 @@ import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormV
 import { CollectionView, CollectionViewType } from './CollectionView';
 import "./TabDocView.scss";
 import React = require("react");
-import Color = require('color');
-import { Colors, Shadows } from '../global/globalEnums';
 const _global = (window /* browser */ || global /* node */) as any;
 
 interface TabDocViewProps {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 0b12f6c21..5b9f6139f 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -50,7 +50,6 @@ import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCurso
 import "./CollectionFreeFormView.scss";
 import { MarqueeView } from "./MarqueeView";
 import React = require("react");
-import Color = require("color");
 import { ColorScheme } from "../../../util/SettingsManager";
 
 export const panZoomSchema = createSchema({
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index c76a051f7..fe34d6687 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -7,7 +7,7 @@ import { listSpec } from "../../../fields/Schema";
 import { ComputedField } from "../../../fields/ScriptField";
 import { Cast, NumCast, StrCast } from "../../../fields/Types";
 import { TraceMobx } from "../../../fields/util";
-import { numberRange } from "../../../Utils";
+import { DashColor, numberRange } from "../../../Utils";
 import { DocumentManager } from "../../util/DocumentManager";
 import { SelectionManager } from "../../util/SelectionManager";
 import { Transform } from "../../util/Transform";
@@ -18,7 +18,6 @@ import { StyleProp } from "../StyleProvider";
 import "./CollectionFreeFormDocumentView.scss";
 import { DocumentView, DocumentViewProps } from "./DocumentView";
 import React = require("react");
-import Color = require("color");
 
 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;
@@ -165,7 +164,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
             PanelHeight: this.panelHeight,
         };
         const background = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
-        const mixBlendMode = StrCast(this.layoutDoc.mixBlendMode) as any || (typeof background === "string" && Color(background.toLowerCase()).alpha() !== 1 ? "multiply" : undefined);
+        const mixBlendMode = StrCast(this.layoutDoc.mixBlendMode) as any || (typeof background === "string" && DashColor(background).alpha() !== 1 ? "multiply" : undefined);
         return <div className={"collectionFreeFormDocumentView-container"}
             style={{
                 outline: this.Highlight ? "orange solid 2px" : "",
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index add84ff83..8e61a224c 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -30,8 +30,7 @@ import { LightboxView } from "../../LightboxView";
 import { CollectionFreeFormDocumentView } from "../CollectionFreeFormDocumentView";
 import { FieldView, FieldViewProps } from '../FieldView';
 import "./PresBox.scss";
-import Color = require("color");
-import { PresEffect, PresStatus, PresMovement } from "./PresEnums";
+import { PresEffect, PresMovement, PresStatus } from "./PresEnums";
 
 export class PinProps {
     audioRange?: boolean;
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 57bd0f46f..d8690831f 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -1,15 +1,17 @@
+import { IconProp } from "@fortawesome/fontawesome-svg-core";
 import { saveAs } from "file-saver";
 import { action, computed, observable, ObservableMap, runInAction } from "mobx";
 import { computedFn } from "mobx-utils";
 import { alias, map, serializable } from "serializr";
 import { DocServer } from "../client/DocServer";
 import { DocumentType } from "../client/documents/DocumentTypes";
+import { CurrentUserUtils } from "../client/util/CurrentUserUtils";
 import { LinkManager } from "../client/util/LinkManager";
 import { Scripting, scriptingGlobal } from "../client/util/Scripting";
 import { SelectionManager } from "../client/util/SelectionManager";
 import { afterDocDeserialize, autoObject, Deserializable, SerializationHelper } from "../client/util/SerializationHelper";
 import { UndoManager } from "../client/util/UndoManager";
-import { intersectRect, Utils } from "../Utils";
+import { DashColor, intersectRect, Utils } from "../Utils";
 import { DateField } from "./DateField";
 import { Copy, HandleUpdate, Id, OnUpdate, Parent, Self, SelfProxy, ToScriptString, ToString, Update } from "./FieldSymbols";
 import { List } from "./List";
@@ -23,9 +25,6 @@ import { Cast, FieldValue, NumCast, StrCast, ToConstructor } from "./Types";
 import { AudioField, ImageField, PdfField, VideoField, WebField } from "./URLField";
 import { deleteProperty, GetEffectiveAcl, getField, getter, inheritParentAcls, makeEditable, makeReadOnly, normalizeEmail, setter, SharingPermissions, updateFunction } from "./util";
 import JSZip = require("jszip");
-import { CurrentUserUtils } from "../client/util/CurrentUserUtils";
-import { IconProp } from "@fortawesome/fontawesome-svg-core";
-import Color = require("color");
 
 export namespace Field {
     export function toKeyValueString(doc: Doc, key: string): string {
@@ -1089,7 +1088,7 @@ export namespace Doc {
 
     export function matchFieldValue(doc: Doc, key: string, value: any): boolean {
         if (Utils.HasTransparencyFilter(value)) {
-            const isTransparent = (color: string) => color !== "" && (Color(color).alpha() !== 1);
+            const isTransparent = (color: string) => color !== "" && (DashColor(color).alpha() !== 1);
             return isTransparent(StrCast(doc[key]));
         }
         if (typeof value === "string") {
diff --git a/src/fields/RichTextUtils.ts b/src/fields/RichTextUtils.ts
index 0b5f14d74..a19be5df9 100644
--- a/src/fields/RichTextUtils.ts
+++ b/src/fields/RichTextUtils.ts
@@ -2,7 +2,7 @@ import { AssertionError } from "assert";
 import { docs_v1 } from "googleapis";
 import { Fragment, Mark, Node } from "prosemirror-model";
 import { sinkListItem } from "prosemirror-schema-list";
-import { Utils } from "../Utils";
+import { Utils, DashColor } from "../Utils";
 import { Docs, DocUtils } from "../client/documents/Documents";
 import { schema } from "../client/views/nodes/formattedText/schema_rts";
 import { GooglePhotos } from "../client/apis/google_docs/GooglePhotosClientUtils";
@@ -482,7 +482,7 @@ export namespace RichTextUtils {
         }
 
         const fromHex = (color: string): docs_v1.Schema$OptionalColor => {
-            const c = Color(color);
+            const c = DashColor(color);
             return fromRgb.convert(c.red(), c.green(), c.blue());
         };
 
-- 
cgit v1.2.3-70-g09d2

