From f4830de4f8c4794ec98e54be9ba8730e46155c35 Mon Sep 17 00:00:00 2001
From: usodhi <61431818+usodhi@users.noreply.github.com>
Date: Mon, 6 Jul 2020 18:18:17 +0530
Subject: trying first implementation of storing acls

---
 src/client/views/nodes/DocumentContentsView.tsx | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'src/client/views/nodes/DocumentContentsView.tsx')

diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index f1438fd54..d480c76d0 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -36,7 +36,7 @@ import { WebBox } from "./WebBox";
 import { InkingStroke } from "../InkingStroke";
 import React = require("react");
 import { RecommendationsBox } from "../RecommendationsBox";
-import { TraceMobx } from "../../../fields/util";
+import { TraceMobx, getEffectiveAcl } from "../../../fields/util";
 import { ScriptField } from "../../../fields/ScriptField";
 import XRegExp = require("xregexp");
 
@@ -184,8 +184,8 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
 
         const bindings = this.CreateBindings(onClick, onInput);
         //  layoutFrame = splits.length > 1 ? splits[0] + splits[1].replace(/{([^{}]|(?R))*}/, replacer4) : ""; // might have been more elegant if javascript supported recursive patterns
-
-        return (this.props.renderDepth > 12 || !layoutFrame || !this.layoutDoc || this.layoutDoc[AclSym] === AclPrivate) ? (null) :
+        console.log("here");
+        return (this.props.renderDepth > 12 || !layoutFrame || !this.layoutDoc || getEffectiveAcl(this.layoutDoc) === AclPrivate) ? (null) :
             <ObserverJsxParser
                 key={42}
                 blacklistedAttrs={[]}
-- 
cgit v1.2.3-70-g09d2


From 12285b8c0aff514a2345874508c35b6de1026ef4 Mon Sep 17 00:00:00 2001
From: usodhi <61431818+usodhi@users.noreply.github.com>
Date: Thu, 9 Jul 2020 12:25:46 +0530
Subject: acls now work I think + some cleanup

---
 src/client/DocServer.ts                            |  1 -
 src/client/util/GroupManager.tsx                   | 13 +++-
 src/client/util/GroupMemberView.tsx                |  2 +-
 src/client/util/SharingManager.tsx                 |  2 -
 src/client/views/DocComponent.tsx                  |  1 -
 src/client/views/GlobalKeyHandler.ts               |  2 +
 src/client/views/collections/CollectionView.tsx    | 21 +++---
 src/client/views/nodes/DocumentContentsView.tsx    |  1 -
 src/client/views/nodes/DocumentView.tsx            | 22 +++---
 .../views/nodes/formattedText/FormattedTextBox.tsx |  1 -
 src/fields/Doc.ts                                  | 24 +------
 src/fields/util.ts                                 | 84 +++++++++++-----------
 12 files changed, 84 insertions(+), 90 deletions(-)

(limited to 'src/client/views/nodes/DocumentContentsView.tsx')

diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts
index 860a8fd92..bac324c77 100644
--- a/src/client/DocServer.ts
+++ b/src/client/DocServer.ts
@@ -40,7 +40,6 @@ export namespace DocServer {
 
     export var PlaygroundFields: string[];
     export function setPlaygroundFields(livePlaygroundFields: string[]) {
-        console.log("here");
         DocServer.PlaygroundFields = livePlaygroundFields;
         livePlaygroundFields.forEach(f => DocServer.setFieldWriteMode(f, DocServer.WriteMode.LivePlayground));
     }
diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx
index 83b206f94..23bdd248b 100644
--- a/src/client/util/GroupManager.tsx
+++ b/src/client/util/GroupManager.tsx
@@ -14,6 +14,7 @@ import Select from 'react-select';
 import "./GroupManager.scss";
 import { StrCast } from "../../fields/Types";
 import GroupMemberView from "./GroupMemberView";
+import { setGroups } from "../../fields/util";
 
 library.add(fa.faWindowClose);
 
@@ -54,7 +55,7 @@ export default class GroupManager extends React.Component<{}> {
                 if (members.includes(Doc.CurrentUserEmail)) this.currentUserGroups.push(StrCast(group.groupName));
             });
         })
-            .finally(() => console.log(this.currentUserGroups));
+            .finally(() => setGroups(this.currentUserGroups));
 
         // (this.GroupManagerDoc?.data as List<Doc>).forEach(group => {
         //     Promise.resolve(group).then(resolvedGroup => {
@@ -178,6 +179,10 @@ export default class GroupManager extends React.Component<{}> {
         groupDoc.groupName = groupName;
         groupDoc.owners = JSON.stringify([Doc.CurrentUserEmail]);
         groupDoc.members = JSON.stringify(memberEmails);
+        if (memberEmails.includes(Doc.CurrentUserEmail)) {
+            this.currentUserGroups.push(groupName);
+            setGroups(this.currentUserGroups);
+        }
         this.addGroup(groupDoc);
     }
 
@@ -204,6 +209,12 @@ export default class GroupManager extends React.Component<{}> {
                 // SharingManager.Instance.setInternalGroupSharing(group, "Not Shared");
                 Doc.RemoveDocFromList(this.GroupManagerDoc, "data", group);
                 SharingManager.Instance.removeGroup(group);
+                const members: string[] = JSON.parse(StrCast(group.members));
+                if (members.includes(Doc.CurrentUserEmail)) {
+                    const index = this.currentUserGroups.findIndex(groupName => groupName === group.groupName);
+                    index !== -1 && this.currentUserGroups.splice(index, 1);
+                    setGroups(this.currentUserGroups);
+                }
                 if (group === this.currentGroup) {
                     runInAction(() => this.currentGroup = undefined);
                 }
diff --git a/src/client/util/GroupMemberView.tsx b/src/client/util/GroupMemberView.tsx
index cc279b6b2..742caa676 100644
--- a/src/client/util/GroupMemberView.tsx
+++ b/src/client/util/GroupMemberView.tsx
@@ -51,7 +51,7 @@ export default class GroupMemberView extends React.Component<GroupMemberViewProp
                                     }}
                                 />
                             </div>
-                            <button onClick={() => console.log(GroupManager.Instance.deleteGroup(this.props.group))}>Delete group</button>
+                            <button onClick={() => GroupManager.Instance.deleteGroup(this.props.group)}>Delete group</button>
                         </div> :
                         null}
                 </div>
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index bec6b973b..d64302456 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -359,8 +359,6 @@ export default class SharingManager extends React.Component<{}> {
     share = () => {
         this.selectedUsers?.forEach(user => {
             if (user.value.includes(indType)) {
-                console.log(user);
-                console.log(this.users.find(u => u.user.email === user.label));
                 this.setInternalSharing(this.users.find(u => u.user.email === user.label)!, this.permissions);
             }
             else {
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index e8c34d931..781673e59 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -138,7 +138,6 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T
             const targetDataDoc = this.props.Document[DataSym];
             const docList = DocListCast(targetDataDoc[this.annotationKey]);
             const added = docs.filter(d => !docList.includes(d));
-            console.log("here");
             const effectiveAcl = getEffectiveAcl(this.dataDoc);
             if (added.length) {
                 if (effectiveAcl === AclReadonly) {
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index a3a023164..45d53a5f5 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -22,6 +22,7 @@ import { DocumentView } from "./nodes/DocumentView";
 import { DocumentLinksButton } from "./nodes/DocumentLinksButton";
 import PDFMenu from "./pdf/PDFMenu";
 import { ContextMenu } from "./ContextMenu";
+import GroupManager from "../util/GroupManager";
 
 const modifiers = ["control", "meta", "shift", "alt"];
 type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo | Promise<KeyControlInfo>;
@@ -107,6 +108,7 @@ export default class KeyManager {
                 GoogleAuthenticationManager.Instance.cancel();
                 HypothesisAuthenticationManager.Instance.cancel();
                 SharingManager.Instance.close();
+                GroupManager.Instance.close();
                 break;
             case "delete":
             case "backspace":
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 31f0c1df3..6a6a475c8 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -8,7 +8,7 @@ import * as React from 'react';
 import Lightbox from 'react-image-lightbox-with-rotate';
 import 'react-image-lightbox-with-rotate/style.css'; // This only needs to be imported once in your app
 import { DateField } from '../../../fields/DateField';
-import { AclAddonly, AclReadonly, AclSym, DataSym, Doc, DocListCast, Field, Opt } from '../../../fields/Doc';
+import { AclAddonly, AclReadonly, AclSym, DataSym, Doc, DocListCast, Field, Opt, AclEdit } from '../../../fields/Doc';
 import { Id } from '../../../fields/FieldSymbols';
 import { List } from '../../../fields/List';
 import { ObjectField } from '../../../fields/ObjectField';
@@ -132,8 +132,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
         const targetDataDoc = this.props.Document[DataSym];
         const docList = DocListCast(targetDataDoc[this.props.fieldKey]);
         const added = docs.filter(d => !docList.includes(d));
-        console.log("here");
-        const effectiveAcl = getEffectiveAcl(this.dataDoc);
+        const effectiveAcl = getEffectiveAcl(this.props.Document);
         if (added.length) {
             if (effectiveAcl === AclReadonly) {
                 return false;
@@ -167,13 +166,15 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
 
     @action.bound
     removeDocument = (doc: any): boolean => {
-        const docs = doc instanceof Doc ? [doc] : doc as Doc[];
-        const targetDataDoc = this.props.Document[DataSym];
-        const value = DocListCast(targetDataDoc[this.props.fieldKey]);
-        const result = value.filter(v => !docs.includes(v));
-        if (result.length !== value.length) {
-            targetDataDoc[this.props.fieldKey] = new List<Doc>(result);
-            return true;
+        if (getEffectiveAcl(this.props.Document) === AclEdit) {
+            const docs = doc instanceof Doc ? [doc] : doc as Doc[];
+            const targetDataDoc = this.props.Document[DataSym];
+            const value = DocListCast(targetDataDoc[this.props.fieldKey]);
+            const result = value.filter(v => !docs.includes(v));
+            if (result.length !== value.length) {
+                targetDataDoc[this.props.fieldKey] = new List<Doc>(result);
+                return true;
+            }
         }
         return false;
     }
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index d480c76d0..e34ceb994 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -184,7 +184,6 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
 
         const bindings = this.CreateBindings(onClick, onInput);
         //  layoutFrame = splits.length > 1 ? splits[0] + splits[1].replace(/{([^{}]|(?R))*}/, replacer4) : ""; // might have been more elegant if javascript supported recursive patterns
-        console.log("here");
         return (this.props.renderDepth > 12 || !layoutFrame || !this.layoutDoc || getEffectiveAcl(this.layoutDoc) === AclPrivate) ? (null) :
             <ObserverJsxParser
                 key={42}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 1d76633be..b9ae8b444 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -26,7 +26,7 @@ import { InteractionUtils } from '../../util/InteractionUtils';
 import { Scripting } from '../../util/Scripting';
 import { SearchUtil } from '../../util/SearchUtil';
 import { SelectionManager } from "../../util/SelectionManager";
-import SharingManager from '../../util/SharingManager';
+import SharingManager, { SharingPermissions } from '../../util/SharingManager';
 import { Transform } from "../../util/Transform";
 import { undoBatch, UndoManager } from "../../util/UndoManager";
 import { CollectionView, CollectionViewType } from '../collections/CollectionView';
@@ -725,7 +725,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
     @undoBatch
     @action
-    setAcl = (acl: "readOnly" | "addOnly" | "ownerOnly" | "write") => {
+    setAcl = (acl: SharingPermissions) => {
         this.dataDoc.ACL = this.props.Document.ACL = acl;
         DocListCast(this.dataDoc[Doc.LayoutFieldKey(this.dataDoc)]).map(d => {
             if (d.author === Doc.CurrentUserEmail) d.ACL = acl;
@@ -735,7 +735,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     }
     @undoBatch
     @action
-    testAcl = (acl: "readOnly" | "addOnly" | "ownerOnly" | "write") => {
+    testAcl = (acl: SharingPermissions) => {
         this.dataDoc.author = this.props.Document.author = "ADMIN";
         this.dataDoc.ACL = this.props.Document.ACL = acl;
         DocListCast(this.dataDoc[Doc.LayoutFieldKey(this.dataDoc)]).map(d => {
@@ -845,12 +845,12 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
         const existingAcls = cm.findByDescription("Privacy...");
         const aclItems: ContextMenuProps[] = existingAcls && "subitems" in existingAcls ? existingAcls.subitems : [];
-        aclItems.push({ description: "Make Add Only", event: () => this.setAcl("addOnly"), icon: "concierge-bell" });
-        aclItems.push({ description: "Make Read Only", event: () => this.setAcl("readOnly"), icon: "concierge-bell" });
-        aclItems.push({ description: "Make Private", event: () => this.setAcl("ownerOnly"), icon: "concierge-bell" });
-        aclItems.push({ description: "Make Editable", event: () => this.setAcl("write"), icon: "concierge-bell" });
-        aclItems.push({ description: "Test Private", event: () => this.testAcl("ownerOnly"), icon: "concierge-bell" });
-        aclItems.push({ description: "Test Readonly", event: () => this.testAcl("readOnly"), icon: "concierge-bell" });
+        aclItems.push({ description: "Make Add Only", event: () => this.setAcl(SharingPermissions.Add), icon: "concierge-bell" });
+        aclItems.push({ description: "Make Read Only", event: () => this.setAcl(SharingPermissions.View), icon: "concierge-bell" });
+        aclItems.push({ description: "Make Private", event: () => this.setAcl(SharingPermissions.None), icon: "concierge-bell" });
+        aclItems.push({ description: "Make Editable", event: () => this.setAcl(SharingPermissions.Edit), icon: "concierge-bell" });
+        aclItems.push({ description: "Test Private", event: () => this.testAcl(SharingPermissions.None), icon: "concierge-bell" });
+        aclItems.push({ description: "Test Readonly", event: () => this.testAcl(SharingPermissions.View), icon: "concierge-bell" });
         !existingAcls && cm.addItem({ description: "Privacy...", subitems: aclItems, icon: "question" });
 
         // const recommender_subitems: ContextMenuProps[] = [];
@@ -1206,9 +1206,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     }
 
     render() {
-        console.log("here");
-        if (getEffectiveAcl(this.props.Document) === AclPrivate) return (null);
         if (!(this.props.Document instanceof Doc)) return (null);
+        if (getEffectiveAcl(this.props.Document) === AclPrivate) return (null);
+        if (this.props.Document.hidden) return (null);
         const backgroundColor = Doc.UserDoc().renderStyle === "comic" ? undefined : this.props.forcedBackgroundColor?.(this.Document) || StrCast(this.layoutDoc._backgroundColor) || StrCast(this.layoutDoc.backgroundColor) || StrCast(this.Document.backgroundColor) || this.props.backgroundColor?.(this.Document);
         const opacity = Cast(this.layoutDoc._opacity, "number", Cast(this.layoutDoc.opacity, "number", Cast(this.Document.opacity, "number", null)));
         const finalOpacity = this.props.opacity ? this.props.opacity() : opacity;
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index a0dbcd980..ccf83cbf9 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -227,7 +227,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             const curLayout = this.rootDoc !== this.layoutDoc ? Cast(this.layoutDoc[this.fieldKey], RichTextField, null) : undefined; // the default text stored in a layout template
             const json = JSON.stringify(state.toJSON());
             // if (!this.dataDoc[AclSym]) { // what?
-            console.log("here");
             if (getEffectiveAcl(this.dataDoc) === AclEdit) {
                 if (!this._applyingChange && json.replace(/"selection":.*/, "") !== curProto?.Data.replace(/"selection":.*/, "")) {
                     this._applyingChange = true;
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index c965dc282..27eabf451 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -109,7 +109,6 @@ const AclMap = new Map<string, symbol>([
 ]);
 
 export function fetchProto(doc: Doc) {
-    console.log("in fetchproto");
     if (doc.author !== Doc.CurrentUserEmail) { // storing acls for groups needs to be extended here - AclSym should store a datastructure that stores information about permissions
 
         const permissions: { [key: string]: symbol } = {};
@@ -118,22 +117,8 @@ export function fetchProto(doc: Doc) {
             if (key.startsWith("ACL")) permissions[key] = AclMap.get(StrCast(doc[key]))!;
         });
 
-        doc[AclSym] = permissions;
 
-        // const acl = Doc.Get(doc, "ACL", true);
-        // switch (acl) {
-        //     case "ownerOnly":
-        //         doc[AclSym] = AclPrivate;
-        //         return undefined;
-        //     case "readOnly":
-        //         doc[AclSym] = AclReadonly;
-        //         break;
-        //     case "addOnly":
-        //         doc[AclSym] = AclAddonly;
-        //         break;
-        //     // case "edit":
-        //     //     doc[AclSym] = AclEdit;
-        // }
+        if (Object.keys(permissions).length) doc[AclSym] = permissions;
     }
 
     if (doc.proto instanceof Promise) {
@@ -208,7 +193,7 @@ export class Doc extends RefField {
 
     private [Self] = this;
     private [SelfProxy]: any;
-    public [AclSym]: any;
+    public [AclSym]: { [key: string]: symbol };
     public [WidthSym] = () => NumCast(this[SelfProxy]._width);
     public [HeightSym] = () => NumCast(this[SelfProxy]._height);
     public [ToScriptString]() { return `DOC-"${this[Self][Id]}"-`; }
@@ -232,8 +217,8 @@ export class Doc extends RefField {
             return Cast(this[SelfProxy][renderFieldKey + "-layout[" + templateLayoutDoc[Id] + "]"], Doc, null) || templateLayoutDoc;
         }
         return undefined;
-    }
 
+    }
 
     private [CachedUpdates]: { [key: string]: () => void | Promise<any> } = {};
     public static CurrentUserEmail: string = "";
@@ -840,7 +825,6 @@ export namespace Doc {
     }
     // don't bother memoizing (caching) the result if called from a non-reactive context. (plus this avoids a warning message)
     export function IsBrushedDegreeUnmemoized(doc: Doc) {
-        console.log("here");
         if (!doc || getEffectiveAcl(doc) === AclPrivate || getEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return 0;
         return brushManager.BrushedDoc.has(doc) ? 2 : brushManager.BrushedDoc.has(Doc.GetProto(doc)) ? 1 : 0;
     }
@@ -850,7 +834,6 @@ export namespace Doc {
         })(doc);
     }
     export function BrushDoc(doc: Doc) {
-        console.log("here");
         if (!doc || getEffectiveAcl(doc) === AclPrivate || getEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return doc;
         brushManager.BrushedDoc.set(doc, true);
         brushManager.BrushedDoc.set(Doc.GetProto(doc), true);
@@ -888,7 +871,6 @@ export namespace Doc {
     }
     const highlightManager = new HighlightBrush();
     export function IsHighlighted(doc: Doc) {
-        console.log("here");
         if (!doc || getEffectiveAcl(doc) === AclPrivate || getEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return false;
         return highlightManager.HighlightedDoc.get(doc) || highlightManager.HighlightedDoc.get(Doc.GetProto(doc));
     }
diff --git a/src/fields/util.ts b/src/fields/util.ts
index a3e7a36f8..a1af1d3c5 100644
--- a/src/fields/util.ts
+++ b/src/fields/util.ts
@@ -1,5 +1,5 @@
 import { UndoManager } from "../client/util/UndoManager";
-import { Doc, Field, FieldResult, UpdatingFromServer, LayoutSym, AclSym, AclPrivate, AclEdit, AclReadonly, AclAddonly } from "./Doc";
+import { Doc, FieldResult, UpdatingFromServer, LayoutSym, AclPrivate, AclEdit, AclReadonly, AclAddonly, AclSym, fetchProto } from "./Doc";
 import { SerializationHelper } from "../client/util/SerializationHelper";
 import { ProxyField, PrefetchProxy } from "./Proxy";
 import { RefField } from "./RefField";
@@ -9,7 +9,6 @@ import { Parent, OnUpdate, Update, Id, SelfProxy, Self } from "./FieldSymbols";
 import { DocServer } from "../client/DocServer";
 import { ComputedField } from "./ScriptField";
 import { ScriptCast } from "./Types";
-import GroupManager from "../client/util/GroupManager";
 
 
 function _readOnlySetter(): never {
@@ -108,57 +107,65 @@ export function OVERRIDE_ACL(val: boolean) {
     _overrideAcl = val;
 }
 
-const HierarchyMapping = new Map<symbol, number>([
-    [AclPrivate, 0],
-    [AclReadonly, 1],
-    [AclAddonly, 2],
-    [AclEdit, 3]
-]);
+let currentUserGroups: string[] = [];
+let currentUserEmail: string;// = Doc.CurrentUserEmail;
 
-export function getEffectiveAcl(target: any): symbol {
+export function setGroups(groups: string[]) {
+    currentUserGroups = groups;
+    currentUserEmail = Doc.CurrentUserEmail;
+}
 
-    console.log("in getEffectiveAcl");
 
-    if (target[AclSym].ACL) return target[AclSym].ACL;
+export function getEffectiveAcl(target: any, in_prop?: string | symbol | number): symbol {
 
-    let effectiveAcl = AclEdit;
+    const HierarchyMapping = new Map<symbol, number>([
+        [AclPrivate, 0],
+        [AclReadonly, 1],
+        [AclAddonly, 2],
+        [AclEdit, 3]
+    ]);
 
-    for (const [key, value] of Object.entries(target[AclSym])) {
-        if (key.startsWith("ACL-")) {
-            if (GroupManager.Instance.currentUserGroups.includes(key.substring(4)) || Doc.CurrentUserEmail === key.substring(4).replace("_", ".")) {
-                if (HierarchyMapping.get(value as symbol)! > HierarchyMapping.get(effectiveAcl)!) {
-                    effectiveAcl = value as symbol;
-                    if (effectiveAcl === AclEdit) break;
-                }
-            }
-        }
+    if (!target[AclSym] && target instanceof Doc) {
+        fetchProto(target);
     }
 
-    return effectiveAcl;
-}
+    if (target[AclSym] && Object.keys(target[AclSym]).length) {
+
+        if (target.author === currentUserEmail) return AclEdit;
+
+        if (_overrideAcl || (in_prop && DocServer.PlaygroundFields?.includes(in_prop.toString()))) return AclEdit;
 
-function testPermission(target: any, in_prop: string | symbol | number): boolean {
+        if (target[AclSym].ACL) return target[AclSym].ACL;
 
-    console.log("here");
-    // if (target[AclSym].ACL !== AclEdit && !_overrideAcl && !DocServer.PlaygroundFields.includes(in_prop.toString())) return false;
-    if (target[AclSym].ACL === AclEdit) return true;
-    for (const [key, value] of Object.entries(target[AclSym])) {
-        if (key.startsWith("ACL-")) {
-            if (GroupManager.Instance.currentUserGroups.includes(key.substring(4))) {
-                if (value === AclEdit) return true;
+        let effectiveAcl = AclPrivate;
+        let aclPresent = false;
+
+        for (const [key, value] of Object.entries(target[AclSym])) {
+            if (key.startsWith("ACL-")) {
+                if (currentUserGroups.includes(key.substring(4)) || currentUserEmail === key.substring(4).replace("_", ".")) {
+                    if (HierarchyMapping.get(value as symbol)! >= HierarchyMapping.get(effectiveAcl)!) {
+                        aclPresent = true;
+                        effectiveAcl = value as symbol;
+                        if (effectiveAcl === AclEdit) break;
+                    }
+                }
             }
         }
+        return aclPresent ? effectiveAcl : AclEdit;
+    }
+    else {
+        return AclEdit;
     }
-    return _overrideAcl || DocServer.PlaygroundFields.includes(in_prop.toString());
 }
 
+
 const layoutProps = ["panX", "panY", "width", "height", "nativeWidth", "nativeHeight", "fitWidth", "fitToBox",
     "chromeStatus", "viewType", "gridGap", "xMargin", "yMargin", "autoHeight"];
 export function setter(target: any, in_prop: string | symbol | number, value: any, receiver: any): boolean {
-    console.log("in setter")
     let prop = in_prop;
-    // if (target[AclSym] && !_overrideAcl && !DocServer.PlaygroundFields.includes(in_prop.toString())) return true; // generalise to a testpermission function
-    if (!testPermission(target, in_prop)) return true;
+    if (getEffectiveAcl(target, in_prop) !== AclEdit) {
+        return true;
+    }
     if (typeof prop === "string" && prop !== "__id" && prop !== "__fields" && (prop.startsWith("_") || layoutProps.includes(prop))) {
         if (!prop.startsWith("_")) {
             console.log(prop + " is deprecated - switch to _" + prop);
@@ -176,11 +183,9 @@ export function setter(target: any, in_prop: string | symbol | number, value: an
 }
 
 export function getter(target: any, in_prop: string | symbol | number, receiver: any): any {
-    console.log("in getter")
     let prop = in_prop;
-    const effectiveAcl = getEffectiveAcl(target);
-    if (in_prop === AclSym) return _overrideAcl ? undefined : effectiveAcl;
-    if (effectiveAcl === AclPrivate && !_overrideAcl) return undefined;
+    if (in_prop === AclSym) return _overrideAcl ? undefined : target[AclSym];
+    if (getEffectiveAcl(target) === AclPrivate && !_overrideAcl) return undefined;
     if (prop === LayoutSym) {
         return target.__LAYOUT__;
     }
@@ -217,7 +222,6 @@ function getFieldImpl(target: any, prop: string | number, receiver: any, ignoreP
     }
     if (field === undefined && !ignoreProto && prop !== "proto") {
         const proto = getFieldImpl(target, "proto", receiver, true);//TODO tfs: instead of receiver we could use target[SelfProxy]... I don't which semantics we want or if it really matters
-        console.log("here");
         if (proto instanceof Doc && getEffectiveAcl(proto) !== AclPrivate) {
             return getFieldImpl(proto[Self], prop, receiver, ignoreProto);
         }
-- 
cgit v1.2.3-70-g09d2


From d70c9004215aea00514030be4137ccc2247b541a Mon Sep 17 00:00:00 2001
From: usodhi <61431818+usodhi@users.noreply.github.com>
Date: Thu, 9 Jul 2020 12:42:20 +0530
Subject: removed some unnecessary imports

---
 src/client/util/SharingManager.tsx                        | 2 +-
 src/client/views/DocComponent.tsx                         | 2 +-
 src/client/views/collections/CollectionView.tsx           | 2 +-
 src/client/views/nodes/DocumentContentsView.tsx           | 2 +-
 src/client/views/nodes/DocumentView.tsx                   | 2 +-
 src/client/views/nodes/formattedText/FormattedTextBox.tsx | 3 +--
 6 files changed, 6 insertions(+), 7 deletions(-)

(limited to 'src/client/views/nodes/DocumentContentsView.tsx')

diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index d64302456..fd3b2dd04 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -1,7 +1,7 @@
 import { observable, runInAction, action } from "mobx";
 import * as React from "react";
 import MainViewModal from "../views/MainViewModal";
-import { Doc, Opt, DocCastAsync, DocListCast } from "../../fields/Doc";
+import { Doc, Opt, DocListCast } from "../../fields/Doc";
 import { DocServer } from "../DocServer";
 import { Cast, StrCast } from "../../fields/Types";
 import * as RequestPromise from "request-promise";
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index 781673e59..43ffe225f 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -1,4 +1,4 @@
-import { Doc, Opt, DataSym, DocListCast, AclSym, AclReadonly, AclAddonly } from '../../fields/Doc';
+import { Doc, Opt, DataSym, DocListCast, AclReadonly, AclAddonly } from '../../fields/Doc';
 import { Touchable } from './Touchable';
 import { computed, action, observable } from 'mobx';
 import { Cast, BoolCast, ScriptCast } from '../../fields/Types';
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 6a6a475c8..032012b2d 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -8,7 +8,7 @@ import * as React from 'react';
 import Lightbox from 'react-image-lightbox-with-rotate';
 import 'react-image-lightbox-with-rotate/style.css'; // This only needs to be imported once in your app
 import { DateField } from '../../../fields/DateField';
-import { AclAddonly, AclReadonly, AclSym, DataSym, Doc, DocListCast, Field, Opt, AclEdit } from '../../../fields/Doc';
+import { AclAddonly, AclReadonly, DataSym, Doc, DocListCast, Field, Opt, AclEdit } from '../../../fields/Doc';
 import { Id } from '../../../fields/FieldSymbols';
 import { List } from '../../../fields/List';
 import { ObjectField } from '../../../fields/ObjectField';
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index e34ceb994..1e6966c05 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -1,6 +1,6 @@
 import { computed } from "mobx";
 import { observer } from "mobx-react";
-import { Doc, Opt, Field, AclSym, AclPrivate } from "../../../fields/Doc";
+import { Doc, Opt, Field, AclPrivate } from "../../../fields/Doc";
 import { Cast, StrCast, NumCast } from "../../../fields/Types";
 import { OmitKeys, Without, emptyPath } from "../../../Utils";
 import { DirectoryImportBox } from "../../util/Import & Export/DirectoryImportBox";
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index b9ae8b444..9dc30c683 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -4,7 +4,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, observable, runInAction } from "mobx";
 import { observer } from "mobx-react";
 import * as rp from "request-promise";
-import { Doc, DocListCast, HeightSym, Opt, WidthSym, DataSym, AclSym, AclReadonly, AclPrivate } from "../../../fields/Doc";
+import { Doc, DocListCast, HeightSym, Opt, WidthSym, DataSym, AclPrivate } from "../../../fields/Doc";
 import { Document } from '../../../fields/documentSchemas';
 import { Id } from '../../../fields/FieldSymbols';
 import { InkTool } from '../../../fields/InkField';
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index ccf83cbf9..aa89b4a10 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -13,7 +13,7 @@ import { EditorState, NodeSelection, Plugin, TextSelection, Transaction } from "
 import { ReplaceStep } from 'prosemirror-transform';
 import { EditorView } from "prosemirror-view";
 import { DateField } from '../../../../fields/DateField';
-import { DataSym, Doc, DocListCast, DocListCastAsync, Field, HeightSym, Opt, WidthSym, AclSym, AclEdit } from "../../../../fields/Doc";
+import { DataSym, Doc, DocListCast, DocListCastAsync, Field, HeightSym, Opt, WidthSym, AclEdit } from "../../../../fields/Doc";
 import { documentSchema } from '../../../../fields/documentSchemas';
 import applyDevTools = require("prosemirror-dev-tools");
 import { removeMarkWithAttrs } from "./prosemirrorPatches";
@@ -226,7 +226,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             const curProto = Cast(Cast(this.dataDoc.proto, Doc, null)?.[this.fieldKey], RichTextField, null);              // the default text inherited from a prototype
             const curLayout = this.rootDoc !== this.layoutDoc ? Cast(this.layoutDoc[this.fieldKey], RichTextField, null) : undefined; // the default text stored in a layout template
             const json = JSON.stringify(state.toJSON());
-            // if (!this.dataDoc[AclSym]) { // what?
             if (getEffectiveAcl(this.dataDoc) === AclEdit) {
                 if (!this._applyingChange && json.replace(/"selection":.*/, "") !== curProto?.Data.replace(/"selection":.*/, "")) {
                     this._applyingChange = true;
-- 
cgit v1.2.3-70-g09d2


From bc0d6410ac42af595cea1fb242e10e464da321ae Mon Sep 17 00:00:00 2001
From: usodhi <61431818+usodhi@users.noreply.github.com>
Date: Thu, 9 Jul 2020 20:41:28 +0530
Subject: change DocListCast to async in SharingManager + prevented textbox
 from showing up on click

---
 src/client/util/SharingManager.tsx                 | 71 +++++++++++-----------
 src/client/views/DocComponent.tsx                  |  4 +-
 src/client/views/collections/CollectionView.tsx    |  6 +-
 .../collections/collectionFreeForm/MarqueeView.tsx |  6 +-
 src/client/views/nodes/DocumentContentsView.tsx    |  4 +-
 src/client/views/nodes/DocumentView.tsx            |  4 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |  4 +-
 src/fields/Doc.ts                                  | 16 ++---
 src/fields/util.ts                                 | 24 +++-----
 9 files changed, 70 insertions(+), 69 deletions(-)

(limited to 'src/client/views/nodes/DocumentContentsView.tsx')

diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index fd3b2dd04..af68edab6 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -1,7 +1,7 @@
 import { observable, runInAction, action } from "mobx";
 import * as React from "react";
 import MainViewModal from "../views/MainViewModal";
-import { Doc, Opt, DocListCast } from "../../fields/Doc";
+import { Doc, Opt, DocListCastAsync } from "../../fields/Doc";
 import { DocServer } from "../DocServer";
 import { Cast, StrCast } from "../../fields/Types";
 import * as RequestPromise from "request-promise";
@@ -43,19 +43,6 @@ export enum SharingPermissions {
 //     [SharingPermissions.Edit, "green"]
 // ]);
 
-// export const HierarchyMapping = new Map<string, number>([
-//     [SharingPermissions.None, 0],
-//     [SharingPermissions.View, 1],
-//     [SharingPermissions.Add, 2],
-//     [SharingPermissions.Edit, 3]
-
-//     // ["0", SharingPermissions.None],
-//     // ["1", SharingPermissions.View],
-//     // ["2", SharingPermissions.Add],
-//     // ["3", SharingPermissions.Edit]
-
-// ]);
-
 interface GroupOptions {
     label: string;
     options: UserOptions[];
@@ -88,8 +75,6 @@ export default class SharingManager extends React.Component<{}> {
     @observable private overlayOpacity = 0.4;
     @observable private selectedUsers: UserOptions[] | null = null;
     @observable private permissions: SharingPermissions = SharingPermissions.Edit;
-    @observable private sharedUsers: ValidatedUser[] = [];
-    @observable private sharedGroups: Doc[] = [];
 
     // private get linkVisible() {
     //     return this.sharingDoc ? this.sharingDoc[PublicKey] !== SharingPermissions.None : false;
@@ -162,13 +147,16 @@ export default class SharingManager extends React.Component<{}> {
 
         target[ACL] = permission;
 
-        group.docsShared ? Doc.IndexOf(target, DocListCast(group.docsShared)) === -1 && (group.docsShared as List<Doc>).push(target) : group.docsShared = new List<Doc>([target]);
+        group.docsShared ? DocListCastAsync(group.docsShared).then(resolved => Doc.IndexOf(target, resolved!) === -1 && (group.docsShared as List<Doc>).push(target)) : group.docsShared = new List<Doc>([target]);
+        // group.docsShared ? Doc.IndexOf(target, DocListCast(group.docsShared)) === -1 && (group.docsShared as List<Doc>).push(target) : group.docsShared = new List<Doc>([target]);
 
         users.forEach(({ notificationDoc }) => {
 
-            if (permission !== SharingPermissions.None) Doc.IndexOf(target, DocListCast(notificationDoc[storage])) === -1 && Doc.AddDocToList(notificationDoc, storage, target);
-            else Doc.IndexOf(target, DocListCast(notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target);
-
+            DocListCastAsync(notificationDoc[storage]).then(res => console.log(res));
+            DocListCastAsync(notificationDoc[storage]).then(resolved => {
+                if (permission !== SharingPermissions.None) Doc.IndexOf(target, resolved!) === -1 && Doc.AddDocToList(notificationDoc, storage, target);
+                else Doc.IndexOf(target, resolved!) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target);
+            });
         });
     }
 
@@ -176,7 +164,12 @@ export default class SharingManager extends React.Component<{}> {
         const user: ValidatedUser = this.users.find(user => user.user.email === email)!;
 
         if (group.docsShared) {
-            DocListCast(group.docsShared).forEach(doc => Doc.IndexOf(doc, DocListCast(user.notificationDoc[storage])) === -1 && Doc.AddDocToList(user.notificationDoc, storage, doc));
+            DocListCastAsync(group.docsShared).then(docsShared => {
+                docsShared?.forEach(doc => {
+                    DocListCastAsync(user.notificationDoc[storage]).then(resolved => Doc.IndexOf(doc, resolved!) === -1 && Doc.AddDocToList(user.notificationDoc, storage, doc));
+                });
+            });
+            // DocListCast(group.docsShared).forEach(doc => Doc.IndexOf(doc, DocListCast(user.notificationDoc[storage])) === -1 && Doc.AddDocToList(user.notificationDoc, storage, doc));
         }
     }
 
@@ -184,20 +177,28 @@ export default class SharingManager extends React.Component<{}> {
         const user: ValidatedUser = this.users.find(user => user.user.email === email)!;
 
         if (group.docsShared) {
-            DocListCast(group.docsShared).forEach(doc => Doc.IndexOf(doc, DocListCast(user.notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(user.notificationDoc, storage, doc));
+            DocListCastAsync(group.docsShared).then(docsShared => {
+                docsShared?.forEach(doc => {
+                    DocListCastAsync(user.notificationDoc[storage]).then(resolved => Doc.IndexOf(doc, resolved!) !== -1 && Doc.RemoveDocFromList(user.notificationDoc, storage, doc));
+                });
+            });
+            // DocListCast(group.docsShared).forEach(doc => Doc.IndexOf(doc, DocListCast(user.notificationDoc[storage])) === -1 && Doc.AddDocToList(user.notificationDoc, storage, doc));
         }
     }
 
     removeGroup = (group: Doc) => {
         if (group.docsShared) {
-            DocListCast(group.docsShared).forEach(doc => {
-                const ACL = `ACL-${StrCast(group.groupName)}`;
-                doc[ACL] = "Not Shared";
+            DocListCastAsync(group.docsShared).then(resolved => {
+                resolved?.forEach(doc => {
+                    const ACL = `ACL-${StrCast(group.groupName)}`;
+                    doc[ACL] = "Not Shared";
+
+                    const members: string[] = JSON.parse(StrCast(group.members));
+                    const users: ValidatedUser[] = this.users.filter(user => members.includes(user.user.email));
 
-                const members: string[] = JSON.parse(StrCast(group.members));
-                const users: ValidatedUser[] = this.users.filter(user => members.includes(user.user.email));
+                    users.forEach(user => Doc.RemoveDocFromList(user.notificationDoc, storage, doc));
+                });
 
-                users.forEach(user => Doc.RemoveDocFromList(user.notificationDoc, storage, doc));
             });
         }
     }
@@ -217,14 +218,16 @@ export default class SharingManager extends React.Component<{}> {
 
 
         if (permission !== SharingPermissions.None) {
-            !this.sharedUsers.includes(recipient) && this.sharedUsers.push(recipient);
-
-            Doc.IndexOf(target, DocListCast(notificationDoc[storage])) === -1 && Doc.AddDocToList(notificationDoc, storage, target);
+            console.log(target);
+            console.log(notificationDoc);
+            DocListCastAsync(notificationDoc[storage]).then(resolved => {
+                Doc.IndexOf(target, resolved!) === -1 && Doc.AddDocToList(notificationDoc, storage, target);
+            });
         }
         else {
-            const index = this.sharedUsers.findIndex(user => user === recipient);
-            index !== -1 && this.sharedUsers.splice(index, 1);
-            Doc.IndexOf(target, DocListCast(notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target);
+            DocListCastAsync(notificationDoc[storage]).then(resolved => {
+                Doc.IndexOf(target, resolved!) === -1 && Doc.RemoveDocFromList(notificationDoc, storage, target);
+            });
         }
 
     }
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index 43ffe225f..eb58d8a3e 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -7,7 +7,7 @@ import { InteractionUtils } from '../util/InteractionUtils';
 import { List } from '../../fields/List';
 import { DateField } from '../../fields/DateField';
 import { ScriptField } from '../../fields/ScriptField';
-import { getEffectiveAcl } from '../../fields/util';
+import { GetEffectiveAcl } from '../../fields/util';
 
 
 ///  DocComponent returns a generic React base class used by views that don't have 'fieldKey' props (e.g.,CollectionFreeFormDocumentView, DocumentView)
@@ -138,7 +138,7 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T
             const targetDataDoc = this.props.Document[DataSym];
             const docList = DocListCast(targetDataDoc[this.annotationKey]);
             const added = docs.filter(d => !docList.includes(d));
-            const effectiveAcl = getEffectiveAcl(this.dataDoc);
+            const effectiveAcl = GetEffectiveAcl(this.dataDoc);
             if (added.length) {
                 if (effectiveAcl === AclReadonly) {
                     return false;
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 032012b2d..7448ae002 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -17,7 +17,7 @@ import { listSpec } from '../../../fields/Schema';
 import { ComputedField, ScriptField } from '../../../fields/ScriptField';
 import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
 import { ImageField } from '../../../fields/URLField';
-import { TraceMobx, getEffectiveAcl } from '../../../fields/util';
+import { TraceMobx, GetEffectiveAcl } from '../../../fields/util';
 import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from '../../../Utils';
 import { Docs, DocUtils } from '../../documents/Documents';
 import { DocumentType } from '../../documents/DocumentTypes';
@@ -132,7 +132,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
         const targetDataDoc = this.props.Document[DataSym];
         const docList = DocListCast(targetDataDoc[this.props.fieldKey]);
         const added = docs.filter(d => !docList.includes(d));
-        const effectiveAcl = getEffectiveAcl(this.props.Document);
+        const effectiveAcl = GetEffectiveAcl(this.props.Document);
         if (added.length) {
             if (effectiveAcl === AclReadonly) {
                 return false;
@@ -166,7 +166,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
 
     @action.bound
     removeDocument = (doc: any): boolean => {
-        if (getEffectiveAcl(this.props.Document) === AclEdit) {
+        if (GetEffectiveAcl(this.props.Document) === AclEdit) {
             const docs = doc instanceof Doc ? [doc] : doc as Doc[];
             const targetDataDoc = this.props.Document[DataSym];
             const value = DocListCast(targetDataDoc[this.props.fieldKey]);
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index b47236bea..971c501ca 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -1,6 +1,7 @@
 import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
-import { Doc, Opt, DocListCast, DataSym } from "../../../../fields/Doc";
+import { Doc, Opt, DocListCast, DataSym, AclEdit, AclAddonly } from "../../../../fields/Doc";
+import { GetEffectiveAcl } from "../../../../fields/util";
 import { InkData, InkField, InkTool } from "../../../../fields/InkField";
 import { List } from "../../../../fields/List";
 import { RichTextField } from "../../../../fields/RichTextField";
@@ -276,7 +277,8 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
         } else {
             this._downX = x;
             this._downY = y;
-            PreviewCursor.Show(x, y, this.onKeyPress, this.props.addLiveTextDocument, this.props.getTransform, this.props.addDocument, this.props.nudge);
+            const effectiveAcl = GetEffectiveAcl(this.props.Document);
+            if (effectiveAcl === AclEdit || effectiveAcl === AclAddonly) PreviewCursor.Show(x, y, this.onKeyPress, this.props.addLiveTextDocument, this.props.getTransform, this.props.addDocument, this.props.nudge);
             this.clearSelection();
         }
     });
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 1e6966c05..f2f8ada68 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -36,7 +36,7 @@ import { WebBox } from "./WebBox";
 import { InkingStroke } from "../InkingStroke";
 import React = require("react");
 import { RecommendationsBox } from "../RecommendationsBox";
-import { TraceMobx, getEffectiveAcl } from "../../../fields/util";
+import { TraceMobx, GetEffectiveAcl } from "../../../fields/util";
 import { ScriptField } from "../../../fields/ScriptField";
 import XRegExp = require("xregexp");
 
@@ -184,7 +184,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
 
         const bindings = this.CreateBindings(onClick, onInput);
         //  layoutFrame = splits.length > 1 ? splits[0] + splits[1].replace(/{([^{}]|(?R))*}/, replacer4) : ""; // might have been more elegant if javascript supported recursive patterns
-        return (this.props.renderDepth > 12 || !layoutFrame || !this.layoutDoc || getEffectiveAcl(this.layoutDoc) === AclPrivate) ? (null) :
+        return (this.props.renderDepth > 12 || !layoutFrame || !this.layoutDoc || GetEffectiveAcl(this.layoutDoc) === AclPrivate) ? (null) :
             <ObserverJsxParser
                 key={42}
                 blacklistedAttrs={[]}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 9dc30c683..7c0bdc6c1 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -12,7 +12,7 @@ import { listSpec } from "../../../fields/Schema";
 import { SchemaHeaderField } from '../../../fields/SchemaHeaderField';
 import { ScriptField } from '../../../fields/ScriptField';
 import { BoolCast, Cast, NumCast, StrCast } from "../../../fields/Types";
-import { TraceMobx, getEffectiveAcl } from '../../../fields/util';
+import { TraceMobx, GetEffectiveAcl } from '../../../fields/util';
 import { GestureUtils } from '../../../pen-gestures/GestureUtils';
 import { emptyFunction, OmitKeys, returnOne, returnTransparent, Utils, emptyPath } from "../../../Utils";
 import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils';
@@ -1207,7 +1207,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
 
     render() {
         if (!(this.props.Document instanceof Doc)) return (null);
-        if (getEffectiveAcl(this.props.Document) === AclPrivate) return (null);
+        if (GetEffectiveAcl(this.props.Document) === AclPrivate) return (null);
         if (this.props.Document.hidden) return (null);
         const backgroundColor = Doc.UserDoc().renderStyle === "comic" ? undefined : this.props.forcedBackgroundColor?.(this.Document) || StrCast(this.layoutDoc._backgroundColor) || StrCast(this.layoutDoc.backgroundColor) || StrCast(this.Document.backgroundColor) || this.props.backgroundColor?.(this.Document);
         const opacity = Cast(this.layoutDoc._opacity, "number", Cast(this.layoutDoc.opacity, "number", Cast(this.Document.opacity, "number", null)));
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index aa89b4a10..0583c7f39 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -24,7 +24,7 @@ import { RichTextField } from "../../../../fields/RichTextField";
 import { RichTextUtils } from '../../../../fields/RichTextUtils';
 import { createSchema, makeInterface } from "../../../../fields/Schema";
 import { Cast, DateCast, NumCast, StrCast, ScriptCast } from "../../../../fields/Types";
-import { TraceMobx, OVERRIDE_ACL, getEffectiveAcl } from '../../../../fields/util';
+import { TraceMobx, OVERRIDE_ACL, GetEffectiveAcl } from '../../../../fields/util';
 import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, returnOne, returnZero, Utils, setupMoveUpEvents } from '../../../../Utils';
 import { GoogleApiClientUtils, Pulls, Pushes } from '../../../apis/google_docs/GoogleApiClientUtils';
 import { DocServer } from "../../../DocServer";
@@ -226,7 +226,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             const curProto = Cast(Cast(this.dataDoc.proto, Doc, null)?.[this.fieldKey], RichTextField, null);              // the default text inherited from a prototype
             const curLayout = this.rootDoc !== this.layoutDoc ? Cast(this.layoutDoc[this.fieldKey], RichTextField, null) : undefined; // the default text stored in a layout template
             const json = JSON.stringify(state.toJSON());
-            if (getEffectiveAcl(this.dataDoc) === AclEdit) {
+            if (GetEffectiveAcl(this.dataDoc) === AclEdit) {
                 if (!this._applyingChange && json.replace(/"selection":.*/, "") !== curProto?.Data.replace(/"selection":.*/, "")) {
                     this._applyingChange = true;
                     (curText !== Cast(this.dataDoc[this.fieldKey], RichTextField)?.Text) && (this.dataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now())));
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 27eabf451..e8dca5fb6 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -17,7 +17,7 @@ import { RichTextField } from "./RichTextField";
 import { listSpec } from "./Schema";
 import { ComputedField } from "./ScriptField";
 import { Cast, FieldValue, NumCast, StrCast, ToConstructor } from "./Types";
-import { deleteProperty, getField, getter, makeEditable, makeReadOnly, setter, updateFunction, getEffectiveAcl } from "./util";
+import { deleteProperty, getField, getter, makeEditable, makeReadOnly, setter, updateFunction, GetEffectiveAcl } from "./util";
 import { LinkManager } from "../client/util/LinkManager";
 import { SharingPermissions } from "../client/util/SharingManager";
 
@@ -136,10 +136,10 @@ export class Doc extends RefField {
             set: setter,
             get: getter,
             // getPrototypeOf: (target) => Cast(target[SelfProxy].proto, Doc) || null, // TODO this might be able to replace the proto logic in getter
-            has: (target, key) => getEffectiveAcl(target) !== AclPrivate && key in target.__fields,
+            has: (target, key) => GetEffectiveAcl(target) !== AclPrivate && key in target.__fields,
             ownKeys: target => {
                 const obj = {} as any;
-                if (getEffectiveAcl(target) !== AclPrivate) Object.assign(obj, target.___fields);
+                if (GetEffectiveAcl(target) !== AclPrivate) Object.assign(obj, target.___fields);
                 runInAction(() => obj.__LAYOUT__ = target.__LAYOUT__);
                 return Object.keys(obj);
             },
@@ -197,7 +197,7 @@ export class Doc extends RefField {
     public [WidthSym] = () => NumCast(this[SelfProxy]._width);
     public [HeightSym] = () => NumCast(this[SelfProxy]._height);
     public [ToScriptString]() { return `DOC-"${this[Self][Id]}"-`; }
-    public [ToString]() { return `Doc(${getEffectiveAcl(this) === AclPrivate ? "-inaccessible-" : this.title})`; }
+    public [ToString]() { return `Doc(${GetEffectiveAcl(this) === AclPrivate ? "-inaccessible-" : this.title})`; }
     public get [LayoutSym]() { return this[SelfProxy].__LAYOUT__; }
     public get [DataSym]() {
         const self = this[SelfProxy];
@@ -825,7 +825,7 @@ export namespace Doc {
     }
     // don't bother memoizing (caching) the result if called from a non-reactive context. (plus this avoids a warning message)
     export function IsBrushedDegreeUnmemoized(doc: Doc) {
-        if (!doc || getEffectiveAcl(doc) === AclPrivate || getEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return 0;
+        if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return 0;
         return brushManager.BrushedDoc.has(doc) ? 2 : brushManager.BrushedDoc.has(Doc.GetProto(doc)) ? 1 : 0;
     }
     export function IsBrushedDegree(doc: Doc) {
@@ -834,14 +834,14 @@ export namespace Doc {
         })(doc);
     }
     export function BrushDoc(doc: Doc) {
-        if (!doc || getEffectiveAcl(doc) === AclPrivate || getEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return doc;
+        if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return doc;
         brushManager.BrushedDoc.set(doc, true);
         brushManager.BrushedDoc.set(Doc.GetProto(doc), true);
         return doc;
     }
     export function UnBrushDoc(doc: Doc) {
 
-        if (!doc || getEffectiveAcl(doc) === AclPrivate || getEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return doc;
+        if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return doc;
         brushManager.BrushedDoc.delete(doc);
         brushManager.BrushedDoc.delete(Doc.GetProto(doc));
         return doc;
@@ -871,7 +871,7 @@ export namespace Doc {
     }
     const highlightManager = new HighlightBrush();
     export function IsHighlighted(doc: Doc) {
-        if (!doc || getEffectiveAcl(doc) === AclPrivate || getEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return false;
+        if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return false;
         return highlightManager.HighlightedDoc.get(doc) || highlightManager.HighlightedDoc.get(Doc.GetProto(doc));
     }
     export function HighlightDoc(doc: Doc, dataAndDisplayDocs = true) {
diff --git a/src/fields/util.ts b/src/fields/util.ts
index a1af1d3c5..f82ea26e0 100644
--- a/src/fields/util.ts
+++ b/src/fields/util.ts
@@ -108,15 +108,13 @@ export function OVERRIDE_ACL(val: boolean) {
 }
 
 let currentUserGroups: string[] = [];
-let currentUserEmail: string;// = Doc.CurrentUserEmail;
 
 export function setGroups(groups: string[]) {
     currentUserGroups = groups;
-    currentUserEmail = Doc.CurrentUserEmail;
 }
 
 
-export function getEffectiveAcl(target: any, in_prop?: string | symbol | number): symbol {
+export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number): symbol {
 
     const HierarchyMapping = new Map<symbol, number>([
         [AclPrivate, 0],
@@ -131,7 +129,7 @@ export function getEffectiveAcl(target: any, in_prop?: string | symbol | number)
 
     if (target[AclSym] && Object.keys(target[AclSym]).length) {
 
-        if (target.author === currentUserEmail) return AclEdit;
+        if (target.author === Doc.CurrentUserEmail || currentUserGroups.includes("admin")) return AclEdit;
 
         if (_overrideAcl || (in_prop && DocServer.PlaygroundFields?.includes(in_prop.toString()))) return AclEdit;
 
@@ -141,13 +139,11 @@ export function getEffectiveAcl(target: any, in_prop?: string | symbol | number)
         let aclPresent = false;
 
         for (const [key, value] of Object.entries(target[AclSym])) {
-            if (key.startsWith("ACL-")) {
-                if (currentUserGroups.includes(key.substring(4)) || currentUserEmail === key.substring(4).replace("_", ".")) {
-                    if (HierarchyMapping.get(value as symbol)! >= HierarchyMapping.get(effectiveAcl)!) {
-                        aclPresent = true;
-                        effectiveAcl = value as symbol;
-                        if (effectiveAcl === AclEdit) break;
-                    }
+            if (currentUserGroups.includes(key.substring(4)) || Doc.CurrentUserEmail === key.substring(4).replace("_", ".")) {
+                if (HierarchyMapping.get(value as symbol)! >= HierarchyMapping.get(effectiveAcl)!) {
+                    aclPresent = true;
+                    effectiveAcl = value as symbol;
+                    if (effectiveAcl === AclEdit) break;
                 }
             }
         }
@@ -163,7 +159,7 @@ const layoutProps = ["panX", "panY", "width", "height", "nativeWidth", "nativeHe
     "chromeStatus", "viewType", "gridGap", "xMargin", "yMargin", "autoHeight"];
 export function setter(target: any, in_prop: string | symbol | number, value: any, receiver: any): boolean {
     let prop = in_prop;
-    if (getEffectiveAcl(target, in_prop) !== AclEdit) {
+    if (GetEffectiveAcl(target, in_prop) !== AclEdit) {
         return true;
     }
     if (typeof prop === "string" && prop !== "__id" && prop !== "__fields" && (prop.startsWith("_") || layoutProps.includes(prop))) {
@@ -185,7 +181,7 @@ export function setter(target: any, in_prop: string | symbol | number, value: an
 export function getter(target: any, in_prop: string | symbol | number, receiver: any): any {
     let prop = in_prop;
     if (in_prop === AclSym) return _overrideAcl ? undefined : target[AclSym];
-    if (getEffectiveAcl(target) === AclPrivate && !_overrideAcl) return undefined;
+    if (GetEffectiveAcl(target) === AclPrivate && !_overrideAcl) return undefined;
     if (prop === LayoutSym) {
         return target.__LAYOUT__;
     }
@@ -222,7 +218,7 @@ function getFieldImpl(target: any, prop: string | number, receiver: any, ignoreP
     }
     if (field === undefined && !ignoreProto && prop !== "proto") {
         const proto = getFieldImpl(target, "proto", receiver, true);//TODO tfs: instead of receiver we could use target[SelfProxy]... I don't which semantics we want or if it really matters
-        if (proto instanceof Doc && getEffectiveAcl(proto) !== AclPrivate) {
+        if (proto instanceof Doc && GetEffectiveAcl(proto) !== AclPrivate) {
             return getFieldImpl(proto[Self], prop, receiver, ignoreProto);
         }
         return undefined;
-- 
cgit v1.2.3-70-g09d2


From 3bcc0e3a8ce4ab67dff4b3d62191c346764aa351 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 23 Jul 2020 11:56:05 -0400
Subject: got rid of lots of console.logs().  fixed fonticon box to show a
 'label' if defined otherwise 'title'.  if neither, then it shows no tooltip.

---
 src/client/ClientRecommender.tsx                   |  2 --
 src/client/apis/IBM_Recommender.ts                 |  2 --
 .../apis/google_docs/GooglePhotosClientUtils.ts    |  2 --
 src/client/cognitive_services/CognitiveServices.ts |  2 --
 src/client/documents/Documents.ts                  |  3 ++-
 src/client/util/CurrentUserUtils.ts                |  1 -
 src/client/util/DictationManager.ts                |  2 +-
 src/client/util/InteractionUtils.tsx               |  2 --
 src/client/util/ScriptManager.ts                   | 10 ---------
 src/client/util/SearchUtil.ts                      |  1 -
 src/client/util/SelectionManager.ts                |  1 -
 src/client/views/EditableView.tsx                  |  1 -
 src/client/views/GestureOverlay.tsx                |  1 -
 src/client/views/KeyphraseQueryView.tsx            |  1 -
 src/client/views/ScriptBox.tsx                     |  2 +-
 src/client/views/SearchDocBox.tsx                  |  9 --------
 src/client/views/Touchable.tsx                     |  3 ---
 src/client/views/animationtimeline/Keyframe.tsx    |  4 ----
 src/client/views/animationtimeline/Timeline.tsx    |  1 -
 src/client/views/animationtimeline/Track.tsx       |  4 ----
 .../views/collections/CollectionCarousel3DView.tsx |  3 ---
 .../views/collections/CollectionCarouselView.tsx   |  2 --
 .../collections/CollectionMasonryViewFieldRow.tsx  |  1 -
 src/client/views/collections/CollectionMenu.tsx    |  2 +-
 .../views/collections/CollectionSchemaCells.tsx    | 12 -----------
 .../views/collections/CollectionSchemaView.tsx     |  1 -
 src/client/views/collections/CollectionSubView.tsx |  2 --
 .../views/collections/CollectionTreeView.tsx       |  4 ----
 src/client/views/collections/CollectionView.tsx    |  2 +-
 src/client/views/collections/SchemaTable.tsx       |  3 +--
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  2 --
 .../collections/collectionFreeForm/MarqueeView.tsx |  3 ---
 src/client/views/linking/LinkMenu.tsx              |  1 -
 src/client/views/linking/LinkMenuItem.tsx          |  5 -----
 src/client/views/nodes/DocumentContentsView.tsx    |  2 +-
 src/client/views/nodes/DocumentLinksButton.tsx     |  2 --
 src/client/views/nodes/DocumentView.tsx            |  1 -
 src/client/views/nodes/FontIconBox.tsx             | 24 ++++++++++++----------
 src/client/views/nodes/PresBox.tsx                 |  1 -
 src/client/views/nodes/RadialMenu.tsx              |  1 -
 src/client/views/nodes/ScreenshotBox.tsx           |  2 +-
 src/client/views/nodes/ScriptingBox.tsx            |  1 -
 src/client/views/nodes/VideoBox.tsx                |  2 +-
 src/client/views/nodes/WebBox.tsx                  |  2 +-
 .../views/nodes/formattedText/DashDocView.tsx      |  2 +-
 .../views/nodes/formattedText/RichTextSchema.tsx   |  2 +-
 src/client/views/search/FilterBox.tsx              |  1 -
 src/client/views/search/SearchBox.tsx              |  5 +----
 src/client/views/search/ToggleBar.tsx              |  1 -
 src/fields/Doc.ts                                  |  1 -
 src/fields/ScriptField.ts                          |  1 -
 src/fields/util.ts                                 |  1 -
 src/server/Recommender.ts                          |  4 ----
 src/server/downsize.ts                             |  2 +-
 54 files changed, 28 insertions(+), 127 deletions(-)

(limited to 'src/client/views/nodes/DocumentContentsView.tsx')

diff --git a/src/client/ClientRecommender.tsx b/src/client/ClientRecommender.tsx
index d18669b02..3f875057e 100644
--- a/src/client/ClientRecommender.tsx
+++ b/src/client/ClientRecommender.tsx
@@ -50,7 +50,6 @@ export class ClientRecommender extends React.Component<RecommenderProps> {
     @observable private corr_matrix = [[0, 0], [0, 0]]; // for testing
 
     constructor(props: RecommenderProps) {
-        //console.log("creating client recommender...");
         super(props);
         if (!ClientRecommender.Instance) ClientRecommender.Instance = this;
         ClientRecommender.Instance.docVectors = new Set();
@@ -383,7 +382,6 @@ export class ClientRecommender extends React.Component<RecommenderProps> {
                         case 200:
                             const title_vals: string[] = [];
                             const url_vals: string[] = [];
-                            //console.log(result);
                             if (xml) {
                                 const titles = xml.getElementsByTagName("title");
                                 let counter = 1;
diff --git a/src/client/apis/IBM_Recommender.ts b/src/client/apis/IBM_Recommender.ts
index 480b9cb1c..e6265fcb5 100644
--- a/src/client/apis/IBM_Recommender.ts
+++ b/src/client/apis/IBM_Recommender.ts
@@ -29,10 +29,8 @@
 //     export const analyze = async (_parameters: any): Promise<Opt<string>> => {
 //         try {
 //             const response = await naturalLanguageUnderstanding.analyze(_parameters);
-//             console.log(response);
 //             return (JSON.stringify(response, null, 2));
 //         } catch (err) {
-//             console.log('error: ', err);
 //             return undefined;
 //         }
 //     };
diff --git a/src/client/apis/google_docs/GooglePhotosClientUtils.ts b/src/client/apis/google_docs/GooglePhotosClientUtils.ts
index 13bfb3a91..92eaf2e73 100644
--- a/src/client/apis/google_docs/GooglePhotosClientUtils.ts
+++ b/src/client/apis/google_docs/GooglePhotosClientUtils.ts
@@ -156,8 +156,6 @@ export namespace GooglePhotos {
             const values = Object.values(ContentCategories).filter(value => value !== ContentCategories.NONE);
             for (const value of values) {
                 const searched = (await ContentSearch({ included: [value] }))?.mediaItems?.map(({ id }) => id);
-                console.log("Searching " + value);
-                console.log(searched);
                 searched?.forEach(async id => {
                     const image = await Cast(idMapping[id], Doc);
                     if (image) {
diff --git a/src/client/cognitive_services/CognitiveServices.ts b/src/client/cognitive_services/CognitiveServices.ts
index 6b0b3e029..80961af14 100644
--- a/src/client/cognitive_services/CognitiveServices.ts
+++ b/src/client/cognitive_services/CognitiveServices.ts
@@ -377,7 +377,6 @@ export namespace CognitiveServices {
                         console.log("successful vectorization!");
                         const vectorValues = new List<number>();
                         indices.forEach((ind: any) => {
-                            //console.log(wordvec.word);
                             vectorValues.push(wordvecs[ind]);
                         });
                         ClientRecommender.Instance.processVector(vectorValues, dataDoc, mainDoc);
@@ -385,7 +384,6 @@ export namespace CognitiveServices {
                     else {
                         console.log("unsuccessful :( word(s) not in vocabulary");
                     }
-                    //console.log(vectorValues.size);
                 }
                 );
             }
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index e2569ec70..cd2792226 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -92,6 +92,7 @@ export interface DocumentOptions {
     layoutKey?: string;
     type?: string;
     title?: string;
+    label?: string;
     toolTip?: string; // tooltip to display on hover
     style?: string;
     page?: number;
@@ -494,7 +495,7 @@ export namespace Docs {
                     Doc.Get.FromJson({ data: device, appendToExisting: { targetDoc: Doc.GetProto(doc) } });
                     Doc.AddDocToList(parentProto, "data", doc);
                 } else if (errors) {
-                    console.log(errors);
+                    console.log("Documents:" + errors);
                 } else {
                     alert("A Buxton document import was completely empty (??)");
                 }
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 23b8f09de..b47cfb33a 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -487,7 +487,6 @@ export class CurrentUserUtils {
     // Sets up mobile menu if it is undefined creates a new one, otherwise returns existing menu
     static setupActiveMobileMenu(doc: Doc) {
         if (doc.activeMobileMenu === undefined) {
-            console.log("undefined");
             doc.activeMobileMenu = this.setupMobileMenu();
         }
         return doc.activeMobileMenu as Doc;
diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts
index 28b1ca6cf..540540642 100644
--- a/src/client/util/DictationManager.ts
+++ b/src/client/util/DictationManager.ts
@@ -121,7 +121,7 @@ export namespace DictationManager {
 
         const listenImpl = (options?: Partial<ListeningOptions>) => {
             if (!recognizer) {
-                console.log(unsupported);
+                console.log("DictationManager:" + unsupported);
                 return unsupported;
             }
             if (isListening) {
diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx
index 473d4a263..8b3614ea7 100644
--- a/src/client/util/InteractionUtils.tsx
+++ b/src/client/util/InteractionUtils.tsx
@@ -161,7 +161,6 @@ export namespace InteractionUtils {
     //     return (
     //         InkOptionsMenu.Instance.getColors().map(color => {
     //             const id1 = "arrowStartTest" + color;
-    //             console.log(color);
     //             <marker id={id1} orient="auto" overflow="visible" refX="0" refY="1" markerWidth="10" markerHeight="7">
     //                 <polygon points="0 0, 3 1, 0 2" fill={"#" + color} />
     //             </marker>;
@@ -383,7 +382,6 @@ export namespace InteractionUtils {
         //                 let dist12 = TwoPointEuclidist(pt1, pt2);
         //                 let dist23 = TwoPointEuclidist(pt2, pt3);
         //                 let dist13 = TwoPointEuclidist(pt1, pt3);
-        //                 console.log(`distances: ${dist12}, ${dist23}, ${dist13}`);
         //                 let dist12close = dist12 < leniency;
         //                 let dist23close = dist23 < leniency;
         //                 let dist13close = dist13 < leniency;
diff --git a/src/client/util/ScriptManager.ts b/src/client/util/ScriptManager.ts
index 785e63d9a..94806a7ba 100644
--- a/src/client/util/ScriptManager.ts
+++ b/src/client/util/ScriptManager.ts
@@ -32,24 +32,17 @@ export class ScriptManager {
     }
 
     public addScript(scriptDoc: Doc): boolean {
-
-        console.log("in add script method");
-
         const scriptList = this.getAllScripts();
         scriptList.push(scriptDoc);
         if (ScriptManager.Instance.ScriptManagerDoc) {
             ScriptManager.Instance.ScriptManagerDoc.data = new List<Doc>(scriptList);
             ScriptManager.addScriptToGlobals(scriptDoc);
-            console.log("script added");
             return true;
         }
         return false;
     }
 
     public deleteScript(scriptDoc: Doc): boolean {
-
-        console.log("in delete script method");
-
         if (scriptDoc.name) {
             Scripting.removeGlobal(StrCast(scriptDoc.name));
         }
@@ -70,7 +63,6 @@ export class ScriptManager {
         Scripting.removeGlobal(StrCast(scriptDoc.name));
 
         const params = Cast(scriptDoc["data-params"], listSpec("string"), []);
-        console.log(params);
         const paramNames = params.reduce((o: string, p: string) => {
             if (params.indexOf(p) === params.length - 1) {
                 o = o + p.split(":")[0].trim();
@@ -82,8 +74,6 @@ export class ScriptManager {
 
         const f = new Function(paramNames, StrCast(scriptDoc.script));
 
-        console.log(scriptDoc.script);
-
         Object.defineProperty(f, 'name', { value: StrCast(scriptDoc.name), writable: false });
 
         let parameters = "(";
diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts
index 1ac68480e..0a01d8ac7 100644
--- a/src/client/util/SearchUtil.ts
+++ b/src/client/util/SearchUtil.ts
@@ -128,7 +128,6 @@ export namespace SearchUtil {
         });
         const result: IdSearchResult = JSON.parse(response);
         const { ids, numFound, highlighting } = result;
-        //console.log(ids.length);
         const docMap = await DocServer.GetRefFields(ids);
         const docs: Doc[] = [];
         for (const id of ids) {
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 9a968aeda..20d881961 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -22,7 +22,6 @@ export namespace SelectionManager {
                 }
 
                 manager.SelectedDocuments.set(docView, true);
-                // console.log(manager.SelectedDocuments);
                 docView.props.whenActiveChanged(true);
             } else if (!ctrlPressed && Array.from(manager.SelectedDocuments.entries()).length > 1) {
                 Array.from(manager.SelectedDocuments.keys()).map(dv => dv !== docView && dv.props.whenActiveChanged(false));
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 25a87ab56..ad61d3f91 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -73,7 +73,6 @@ export class EditableView extends React.Component<EditableProps> {
     //     // this is done because when autosuggest is turned on, the suggestions are passed in as a prop,
     //     // so when the suggestions are passed in, and no editing prop is passed in, it used to set it
     //     // to false. this will no longer do so -syip
-    //     console.log("props editing = " + nextProps.editing);
     //     if (nextProps.editing && nextProps.editing !== this._editing) {
     //         this._editing = nextProps.editing;
     //         EditableView.loadId = "";
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index b0b0d72b1..2e588ceb5 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -160,7 +160,6 @@ export default class GestureOverlay extends Touchable {
             if (nts.nt.length === 1) {
                 // -- radial menu code --
                 this._holdTimer = setTimeout(() => {
-                    console.log("hold");
                     const target = document.elementFromPoint(te.changedTouches?.item(0).clientX, te.changedTouches?.item(0).clientY);
                     const pt: any = te.touches[te.touches?.length - 1];
                     if (nts.nt.length === 1 && pt.radiusX > 1 && pt.radiusY > 1) {
diff --git a/src/client/views/KeyphraseQueryView.tsx b/src/client/views/KeyphraseQueryView.tsx
index 1dc156968..13d52db88 100644
--- a/src/client/views/KeyphraseQueryView.tsx
+++ b/src/client/views/KeyphraseQueryView.tsx
@@ -11,7 +11,6 @@ export interface KP_Props {
 export class KeyphraseQueryView extends React.Component<KP_Props>{
     constructor(props: KP_Props) {
         super(props);
-        console.log("FIRST KEY PHRASE: ", props.keyphrases[0]);
     }
 
     render() {
diff --git a/src/client/views/ScriptBox.tsx b/src/client/views/ScriptBox.tsx
index 888f84dfa..2c185be86 100644
--- a/src/client/views/ScriptBox.tsx
+++ b/src/client/views/ScriptBox.tsx
@@ -39,7 +39,7 @@ export class ScriptBox extends React.Component<ScriptBoxProps> {
 
     @action
     onError = (error: string) => {
-        console.log(error);
+        console.log("ScriptBox: " + error);
     }
 
     overlayDisposer?: () => void;
diff --git a/src/client/views/SearchDocBox.tsx b/src/client/views/SearchDocBox.tsx
index e038d8213..084f952a3 100644
--- a/src/client/views/SearchDocBox.tsx
+++ b/src/client/views/SearchDocBox.tsx
@@ -60,8 +60,6 @@ export class SearchDocBox extends React.Component<FieldViewProps> {
 
     componentDidMount() {
         runInAction(() => {
-            console.log("didit"
-            );
             this.query = StrCast(this.props.Document.searchText);
             this.content = (Docs.Create.TreeDocument(DocListCast(Doc.GetProto(this.props.Document).data), { _width: 200, _height: 400, _chromeStatus: "disabled", title: `Search Docs:` + this.query }));
 
@@ -83,12 +81,9 @@ export class SearchDocBox extends React.Component<FieldViewProps> {
         if (newKey.length > 1) {
             const newdocs = await this.getAllResults(this.query);
             const things = newdocs.docs;
-            console.log(things);
-            console.log(this.content);
             runInAction(() => {
                 this.content = Docs.Create.TreeDocument(things, { _width: 200, _height: 400, _chromeStatus: "disabled", title: `Search Docs:` + this.query });
             });
-            console.log(this.content);
         }
 
 
@@ -150,12 +145,9 @@ export class SearchDocBox extends React.Component<FieldViewProps> {
     }
 
     enter = async (e: React.KeyboardEvent) => {
-        console.log(e.key);
         if (e.key === "Enter") {
             const newdocs = await this.getAllResults(this.query);
-            console.log(newdocs.docs);
             this.content = Docs.Create.TreeDocument(newdocs.docs, { _width: 200, _height: 400, _chromeStatus: "disabled", title: `Search Docs: "Results"` });
-
         }
     }
 
@@ -256,7 +248,6 @@ export class SearchDocBox extends React.Component<FieldViewProps> {
     startDragCollection = async () => {
         const res = await this.getAllResults(FilterBox.Instance.getFinalQuery(this._searchString));
         const filtered = FilterBox.Instance.filterDocsByType(res.docs);
-        // console.log(this._results)
         const docs = filtered.map(doc => {
             const isProto = Doc.GetT(doc, "isPrototype", "boolean", true);
             if (isProto) {
diff --git a/src/client/views/Touchable.tsx b/src/client/views/Touchable.tsx
index 5e48d5ffb..c4cae7e8d 100644
--- a/src/client/views/Touchable.tsx
+++ b/src/client/views/Touchable.tsx
@@ -54,7 +54,6 @@ export abstract class Touchable<T = {}> extends React.Component<T> {
             }
         });
 
-        // console.log(ptsToDelete.length);
         ptsToDelete.forEach(pt => this.prevPoints.delete(pt));
 
         if (this.prevPoints.size) {
@@ -86,7 +85,6 @@ export abstract class Touchable<T = {}> extends React.Component<T> {
         // if we're not actually moving a lot, don't consider it as dragging yet
         if (!InteractionUtils.IsDragging(this.prevPoints, myTouches, 5) && !this._touchDrag) return;
         this._touchDrag = true;
-        // console.log(myTouches.length);
         switch (myTouches.length) {
             case 1:
                 this.handle1PointerMove(te, me);
@@ -107,7 +105,6 @@ export abstract class Touchable<T = {}> extends React.Component<T> {
 
     @action
     protected onTouchEnd = (e: Event, me: InteractionUtils.MultiTouchEvent<TouchEvent>): void => {
-        // console.log(InteractionUtils.GetMyTargetTouches(e, this.prevPoints).length + " up");
         // remove all the touches associated with the event
         const te = me.touchEvent;
         for (const pt of me.changedTouches) {
diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx
index 3a7182a94..1b81c544a 100644
--- a/src/client/views/animationtimeline/Keyframe.tsx
+++ b/src/client/views/animationtimeline/Keyframe.tsx
@@ -527,10 +527,6 @@ export class Keyframe extends React.Component<IProps> {
      */
     //154, 206, 223
     render() {
-        trace();
-        console.log(this.props.RegionData.position);
-        console.log(this.regiondata.position);
-        console.log(this.pixelPosition);
         return (
             <div className="bar" ref={this._bar} style={{
                 transform: `translate(${this.pixelPosition}px)`,
diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx
index eac30ca75..df828897e 100644
--- a/src/client/views/animationtimeline/Timeline.tsx
+++ b/src/client/views/animationtimeline/Timeline.tsx
@@ -466,7 +466,6 @@ export class Timeline extends React.Component<FieldViewProps> {
                 //TODO: remove undefineds and duplicates
             }
         });
-        // console.log(longestTime); 
         return longestTime;
     }
 
diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx
index 4987006e7..25c2e68e7 100644
--- a/src/client/views/animationtimeline/Track.tsx
+++ b/src/client/views/animationtimeline/Track.tsx
@@ -134,7 +134,6 @@ export class Track extends React.Component<IProps> {
     autoCreateKeyframe = () => {
         const objects = this.objectWhitelist.map(key => this.props.node[key]);
         intercept(this.props.node, change => {
-            console.log(change);
             return change;
         });
         return reaction(() => {
@@ -174,7 +173,6 @@ export class Track extends React.Component<IProps> {
             if (regiondata) {
                 this.props.node.hidden = false;
                 // if (!this._autoKfReaction) {
-                //     // console.log("creating another reaction"); 
                 //     // this._autoKfReaction = this.autoCreateKeyframe(); 
                 // }
                 this.timeChange();
@@ -204,7 +202,6 @@ export class Track extends React.Component<IProps> {
                     }
                 });
             } else {
-                console.log("reverting state");
                 //this.revertState(); 
             }
         });
@@ -229,7 +226,6 @@ export class Track extends React.Component<IProps> {
             const rightkf: (Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata, this.time); //right keyframe, if it exists        
             const currentkf: (Doc | undefined) = await this.calcCurrent(regiondata); //if the scrubber is on top of the keyframe
             if (currentkf) {
-                console.log("is current");
                 await this.applyKeys(currentkf);
                 this.saveStateKf = currentkf;
                 this.saveStateRegion = regiondata;
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index 8e9970ada..0f3b6f212 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -86,7 +86,6 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
     interval?: number;
     startAutoScroll = (direction: number) => {
         this.interval = window.setInterval(() => {
-            console.log(this.interval, this.scrollSpeed);
             this.changeSlide(direction);
         }, this.scrollSpeed);
     }
@@ -113,13 +112,11 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume
     onPointerDown = (e: React.PointerEvent) => {
         this._downX = e.clientX;
         this._downY = e.clientY;
-        console.log("CAROUSEL down");
         document.addEventListener("pointerup", this.onpointerup);
     }
     private _lastTap: number = 0;
     private _doubleTap = false;
     onpointerup = (e: PointerEvent) => {
-        console.log("CAROUSEL up");
         this._doubleTap = (Date.now() - this._lastTap < 300 && e.button === 0 && Math.abs(e.clientX - this._downX) < 2 && Math.abs(e.clientY - this._downY) < 2);
         this._lastTap = Date.now();
     }
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index 404dc0daa..27aea4b99 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -91,13 +91,11 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument)
     onPointerDown = (e: React.PointerEvent) => {
         this._downX = e.clientX;
         this._downY = e.clientY;
-        console.log("CAROUSEL down");
         document.addEventListener("pointerup", this.onpointerup);
     }
     private _lastTap: number = 0;
     private _doubleTap = false;
     onpointerup = (e: PointerEvent) => {
-        console.log("CAROUSEL up");
         this._doubleTap = (Date.now() - this._lastTap < 300 && e.button === 0 && Math.abs(e.clientX - this._downX) < 2 && Math.abs(e.clientY - this._downY) < 2);
         this._lastTap = Date.now();
     }
diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
index 627b22417..9a7ea2c93 100644
--- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
+++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
@@ -84,7 +84,6 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
 
     @undoBatch
     rowDrop = action((e: Event, de: DragManager.DropEvent) => {
-        console.log("masronry row drop");
         this._createAliasSelected = false;
         if (de.complete.docDragData) {
             (this.props.parent.Document.dropConverter instanceof ScriptField) &&
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 5d95b214a..992c1f600 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -462,7 +462,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
     render() {
         return this.Document.isAnnotationOverlay ? (null) :
             <div className="collectionFreeFormMenu-cont">
-                <div key="back" title="mini map" className="backKeyframe" onClick={this.miniMap}>
+                <div key="map" title="mini map" className="backKeyframe" onClick={this.miniMap}>
                     <FontAwesomeIcon icon={"map"} size={"lg"} />
                 </div>
                 <div key="back" title="back frame" className="backKeyframe" onClick={this.prevKeyframe}>
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index d76b6d204..eecaf7672 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -151,7 +151,6 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
     //     let field = this.props.rowProps.original[this.props.rowProps.column.id as string];
     //     let doc = FieldValue(Cast(field, Doc));
 
-    //     console.log("Expanding doc", StrCast(doc!.title));
     //     this.props.setPreviewDoc(doc!);
 
     //     // this.props.changeFocusedCellByIndex(this.props.row, this.props.col);
@@ -265,7 +264,6 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
                                     return "0";
                                 } else {
                                     const cfield = ComputedField.WithoutComputed(() => FieldValue(props.Document[props.fieldKey]));
-                                    console.log(cfield);
                                     if (type === "number") {
                                         return StrCast(cfield);
                                     }
@@ -286,7 +284,6 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
                                     const script = CompileScript(value, { requiredType: type, typecheck: false, editable: true, addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } });
                                     if (script.compiled) {
                                         retVal = this.applyToDoc(props.Document, this.props.row, this.props.col, script.run);
-                                        console.log("compiled");
                                     }
 
                                 }
@@ -350,17 +347,13 @@ export class CollectionSchemaDateCell extends CollectionSchemaCell {
 
     @action
     handleChange = (date: any) => {
-        console.log(date);
         this._date = date;
         // const script = CompileScript(date.toString(), { requiredType: "Date", addReturn: true, params: { this: Doc.name } });
         // if (script.compiled) {
-        //     console.log("scripting");
         //     this.applyToDoc(this._document, this.props.row, this.props.col, script.run);
         // } else {
-        console.log(DateCast(date));
         // ^ DateCast is always undefined for some reason, but that is what the field should be set to
         this._document[this.props.rowProps.column.id as string] = date as Date;
-        console.log(this._document[this.props.rowProps.column.id as string]);
         //}
     }
 
@@ -425,8 +418,6 @@ export class CollectionSchemaDocCell extends CollectionSchemaCell {
 
         const results = script.compiled && script.run();
         if (results && results.success) {
-
-            console.log(results.result);
             this._doc = results.result;
             this._document[this.prop.fieldKey] = results.result;
             this._docTitle = this._doc?.title;
@@ -457,10 +448,8 @@ export class CollectionSchemaDocCell extends CollectionSchemaCell {
             this._preview = false;
         } else {
             if (bool) {
-                console.log("show doc");
                 this.props.showDoc(this._doc, this.prop.DataDoc, e.clientX, e.clientY);
             } else {
-                console.log("no doc");
                 this.props.showDoc(undefined);
             }
         }
@@ -675,7 +664,6 @@ export class CollectionSchemaListCell extends CollectionSchemaCell {
 
     @action
     toggleOpened(open: boolean) {
-        console.log("open: " + open);
         this._opened = open;
     }
 
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 3c42a2f1c..5553bbbb7 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -332,7 +332,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
 
     @action
     openHeader = (col: any, screenx: number, screeny: number) => {
-        console.log("header opening");
         this._col = col;
         this._headerOpen = !this._headerOpen;
         this._pointerX = screenx;
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index a147b06a3..8480a56cc 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -340,7 +340,6 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
                 // if ((matches = /(https:\/\/)?photos\.google\.com\/(u\/3\/)?album\/([^\\]+)/g.exec(text)) !== null) {
                 //     const albumId = matches[3];
                 //     const mediaItems = await GooglePhotos.Query.AlbumSearch(albumId);
-                //     console.log(mediaItems);
                 //     return;
                 // }
             }
@@ -381,7 +380,6 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
                     file?.type && files.push(file);
 
                     file?.type === "application/json" && Utils.readUploadedFileAsText(file).then(result => {
-                        console.log(result);
                         const json = JSON.parse(result as string);
                         this.addDocument(Docs.Create.TreeDocument(
                             json["rectangular-puzzle"].crossword.clues[0].clue.map((c: any) => {
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 96a2e23c9..651357e5d 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -796,9 +796,6 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
         </div >;
     }
 
-    onKeyPress = (e: React.KeyboardEvent) => {
-        console.log(e);
-    }
     onChildClick = () => {
         return this.props.onChildClick?.() || ScriptCast(this.doc.onChildClick);
     }
@@ -819,7 +816,6 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
                         paddingTop: `${NumCast(this.doc._yPadding, 20)}px`,
                         pointerEvents: !this.props.active() && !SnappingManager.GetIsDragging() ? "none" : undefined
                     }}
-                    onKeyPress={this.onKeyPress}
                     onWheel={(e) => this._mainEle && this._mainEle.scrollHeight > this._mainEle.clientHeight && e.stopPropagation()}
                     onDrop={this.onTreeDrop}
                     ref={this.createTreeDropTarget}>
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 53fd83f26..e2f78d6f9 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -167,7 +167,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
                         const context = Cast(doc.context, Doc, null);
                         if (context && (context.type === DocumentType.VID || context.type === DocumentType.WEB || context.type === DocumentType.PDF || context.type === DocumentType.IMG)) {
                             const pushpin = Docs.Create.FontIconDocument({
-                                title: "pushpin",
+                                title: "pushpin", label: "",
                                 icon: "map-pin", x: Cast(doc.x, "number", null), y: Cast(doc.y, "number", null), _backgroundColor: "#0000003d", color: "#ACCEF7",
                                 _width: 15, _height: 15, _xPadding: 0, isLinkButton: true, displayTimecode: Cast(doc.displayTimecode, "number", null)
                             });
diff --git a/src/client/views/collections/SchemaTable.tsx b/src/client/views/collections/SchemaTable.tsx
index 9e3b4d961..cde795098 100644
--- a/src/client/views/collections/SchemaTable.tsx
+++ b/src/client/views/collections/SchemaTable.tsx
@@ -135,7 +135,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     @action
     changeSorting = (col: any) => {
-        console.log(col.heading);
         if (col.desc === undefined) {
             // no sorting
             this.props.changeColumnSort(col, true);
@@ -149,7 +148,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     @action
-    changeTitleMode = () => { console.log("header clicked"); this._showTitleDropdown = !this._showTitleDropdown; }
+    changeTitleMode = () => this._showTitleDropdown = !this._showTitleDropdown;
 
     @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
     @computed get tableColumns(): Column<Doc>[] {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 3b19a2ab8..979b21321 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -497,10 +497,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
                 const start = this.getTransform().transformPoint(Math.min(...ge.points.map(p => p.X)), Math.min(...ge.points.map(p => p.Y)));
                 this._inkToTextStartX = start[0];
                 this._inkToTextStartY = start[1];
-                console.log("start");
                 break;
             case GestureUtils.Gestures.EndBracket:
-                console.log("end");
                 if (this._inkToTextStartX && this._inkToTextStartY) {
                     const end = this.getTransform().transformPoint(Math.max(...ge.points.map(p => p.X)), Math.max(...ge.points.map(p => p.Y)));
                     const setDocs = this.getActiveDocuments().filter(s => s.proto?.type === "rtf" && s.color);
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 84719b2c9..aa9a3b4ae 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -434,8 +434,6 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
             });
             CognitiveServices.Inking.Appliers.InterpretStrokes(strokes).then((results) => {
                 // const wordResults = results.filter((r: any) => r.category === "inkWord");
-                // console.log(wordResults);
-                // console.log(results);
                 // for (const word of wordResults) {
                 //     const indices: number[] = word.strokeIds;
                 //     indices.forEach(i => {
@@ -476,7 +474,6 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
                 //     });
                 // }
                 const lines = results.filter((r: any) => r.category === "line");
-                console.log(lines);
                 const text = lines.map((l: any) => l.recognizedText).join("\r\n");
                 this.props.addDocument(Docs.Create.TextDocument(text, { _width: this.Bounds.width, _height: this.Bounds.height, x: this.Bounds.left + this.Bounds.width, y: this.Bounds.top, title: text }));
             });
diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx
index 2d151e9bc..7b5fb0127 100644
--- a/src/client/views/linking/LinkMenu.tsx
+++ b/src/client/views/linking/LinkMenu.tsx
@@ -46,7 +46,6 @@ export class LinkMenu extends React.Component<Props> {
 
         if (this._linkMenuRef && !this._linkMenuRef.current?.contains(e.target as any)) {
             if (this._editorRef && !this._editorRef.current?.contains(e.target as any)) {
-                console.log("outside click");
                 DocumentLinksButton.EditLink = undefined;
             }
         }
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index d8ba39f09..d1c839c3b 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -81,10 +81,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
     @action toggleShowMore(e: React.PointerEvent) { e.stopPropagation(); this._showMore = !this._showMore; }
 
     onEdit = (e: React.PointerEvent): void => {
-
-        console.log("Edit");
         LinkManager.currentLink = this.props.linkDoc;
-        console.log(this.props.linkDoc);
         setupMoveUpEvents(this, e, this.editMoved, emptyFunction, () => this.props.showEditor(this.props.linkDoc));
     }
 
@@ -119,7 +116,6 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
         document.addEventListener("pointerup", this.onLinkButtonUp);
 
         if (this._buttonRef && !!!this._buttonRef.current?.contains(e.target as any)) {
-            console.log("outside click");
             LinkDocPreview.LinkInfo = undefined;
         }
     }
@@ -153,7 +149,6 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
 
     @action.bound
     async followDefault() {
-        console.log("FOLLOWWW");
         DocumentLinksButton.EditLink = undefined;
         LinkDocPreview.LinkInfo = undefined;
 
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index f2f8ada68..47dc0a773 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -200,7 +200,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
                 jsx={layoutFrame}
                 showWarnings={true}
 
-                onError={(test: any) => { console.log(test); }}
+                onError={(test: any) => { console.log("DocumentContentsView:" + test); }}
             />;
     }
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 13bec5d7f..b17accfd6 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -68,8 +68,6 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
                 //action(() => Doc.BrushDoc(this.props.View.Document));
                 DocumentLinksButton.StartLink = this.props.View;
             } else if (!this.props.InMenu) {
-                console.log("editing");
-                this.props.View ? console.log("view") : null;
                 DocumentLinksButton.EditLink = this.props.View;
                 DocumentLinksButton.EditLinkLoc = [e.clientX + 10, e.clientY];
             }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 9e492650b..998c6798e 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -910,7 +910,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         if (!ClientRecommender.Instance) new ClientRecommender({ title: "Client Recommender" });
         const documents: Doc[] = [];
         const allDocs = await SearchUtil.GetAllDocs();
-        // allDocs.forEach(doc => console.log(doc.title));
         // clears internal representation of documents as vectors
         ClientRecommender.Instance.reset_docs();
         //ClientRecommender.Instance.arxivrequest("electrons");
diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx
index a4d16fe0e..ab34e13b0 100644
--- a/src/client/views/nodes/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox.tsx
@@ -61,16 +61,18 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>(
     render() {
         const referenceDoc = (this.layoutDoc.dragFactory instanceof Doc ? this.layoutDoc.dragFactory : this.layoutDoc);
         const refLayout = Doc.Layout(referenceDoc);
-        return <Tooltip title={<div className="dash-tooltip">{StrCast(this.layoutDoc.toolTip)}</div>}>
-            <button className="fontIconBox-outerDiv" ref={this._ref} onContextMenu={this.specificContextMenu}
-                style={{
-                    padding: Cast(this.layoutDoc._xPadding, "number", null),
-                    background: StrCast(refLayout._backgroundColor, StrCast(refLayout.backgroundColor)),
-                    boxShadow: this.layoutDoc.ischecked ? `4px 4px 12px black` : undefined
-                }}>
-                <FontAwesomeIcon className="fontIconBox-icon" icon={this.dataDoc.icon as any} color={StrCast(this.layoutDoc.color, this._foregroundColor)} size="sm" />
-                {!this.rootDoc.title ? (null) : <div className="fontIconBox-label"> {StrCast(this.rootDoc.title).substring(0, 6)} </div>}
-            </button>
-        </Tooltip>;
+        const button = <button className="fontIconBox-outerDiv" ref={this._ref} onContextMenu={this.specificContextMenu}
+            style={{
+                padding: Cast(this.layoutDoc._xPadding, "number", null),
+                background: StrCast(refLayout._backgroundColor, StrCast(refLayout.backgroundColor)),
+                boxShadow: this.layoutDoc.ischecked ? `4px 4px 12px black` : undefined
+            }}>
+            <FontAwesomeIcon className="fontIconBox-icon" icon={this.dataDoc.icon as any} color={StrCast(this.layoutDoc.color, this._foregroundColor)} size="sm" />
+            {!this.rootDoc.title ? (null) : <div className="fontIconBox-label" style={{ width: this.rootDoc.label ? "max-content" : undefined }}> {StrCast(this.rootDoc.label, StrCast(this.rootDoc.title).substring(0, 6))} </div>}
+        </button>;
+        return !this.layoutDoc.toolTip ? button :
+            <Tooltip title={<div className="dash-tooltip">{StrCast(this.layoutDoc.toolTip)}</div>}>
+                {button}
+            </Tooltip>;
     }
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index 8818d375e..a304ced18 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -297,7 +297,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         (this.layoutDoc.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false)
 
     render() {
-        // console.log("render = " + this.layoutDoc.title + " " + this.layoutDoc.presStatus);
         // const presOrderedDocs = DocListCast(this.rootDoc.presOrderedDocs);
         // if (presOrderedDocs.length != this.childDocs.length || presOrderedDocs.some((pd, i) => pd !== this.childDocs[i])) {
         //     this.rootDoc.presOrderedDocs = new List<Doc>(this.childDocs.slice());
diff --git a/src/client/views/nodes/RadialMenu.tsx b/src/client/views/nodes/RadialMenu.tsx
index a3ac09a11..7f0956e51 100644
--- a/src/client/views/nodes/RadialMenu.tsx
+++ b/src/client/views/nodes/RadialMenu.tsx
@@ -89,7 +89,6 @@ export class RadialMenu extends React.Component {
 
     @action
     componentDidMount = () => {
-        console.log(this._pageX);
         document.addEventListener("pointerdown", this.onPointerDown);
         document.addEventListener("pointerup", this.onPointerUp);
         this.previewcircle();
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index f7dee0896..1cd29d795 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -112,7 +112,7 @@ export class ScreenshotBox extends ViewBoxBaseComponent<FieldViewProps, Screensh
             return returnedUri;
 
         } catch (e) {
-            console.log(e);
+            console.log("ScreenShotBox:" + e);
         }
     }
     @observable _screenCapture = false;
diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx
index 04ac34cc2..bc43cd473 100644
--- a/src/client/views/nodes/ScriptingBox.tsx
+++ b/src/client/views/nodes/ScriptingBox.tsx
@@ -109,7 +109,6 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps, Sc
     @action
     resetSuggestionPos(caret: any) {
         if (!this._suggestionRef.current || !this._scriptTextRef.current) return;
-        console.log('(top, left, height) = (%s, %s, %s)', caret.top, caret.left, caret.height);
         const suggestionWidth = this._suggestionRef.current.offsetWidth;
         const scriptWidth = this._scriptTextRef.current.offsetWidth;
         const top = caret.top;
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index a5c6c4a48..ee92e517c 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -205,7 +205,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
             return returnedUri;
 
         } catch (e) {
-            console.log(e);
+            console.log("VideoBox :" + e);
         }
     }
     @observable _screenCapture = false;
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 05355caba..39bb7c01d 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -189,7 +189,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
             this.dataDoc[this.fieldKey] = new WebField(URLy);
             this.dataDoc[this.annotationKey] = new List<Doc>([]);
         } catch (e) {
-            console.log("Error in URL :" + this._url);
+            console.log("WebBox URL error:" + this._url);
         }
     }
 
diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx
index 5c3f3dcc9..212da3f3d 100644
--- a/src/client/views/nodes/formattedText/DashDocView.tsx
+++ b/src/client/views/nodes/formattedText/DashDocView.tsx
@@ -209,7 +209,7 @@ export class DashDocView extends React.Component<IDashDocView> {
                 try { // bcz: an exception will be thrown if two aliases are open at the same time when a doc view comment is made
                     view.dispatch(view.state.tr.setNodeMarkup(getPos(), null, { ...node.attrs, width: dashDoc._width + "px", height: dashDoc._height + "px" }));
                 } catch (e) {
-                    console.log(e);
+                    console.log("DashDocView:" + e);
                 }
             }
 
diff --git a/src/client/views/nodes/formattedText/RichTextSchema.tsx b/src/client/views/nodes/formattedText/RichTextSchema.tsx
index 7a50ec3af..33a080fe4 100644
--- a/src/client/views/nodes/formattedText/RichTextSchema.tsx
+++ b/src/client/views/nodes/formattedText/RichTextSchema.tsx
@@ -170,7 +170,7 @@ export class DashDocView {
                             }
                         }
                     } catch (e) {
-                        console.log(e);
+                        console.log("RichTextSchema: " + e);
                     }
                 }
             };
diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx
index 4b53963a5..eb61f9a14 100644
--- a/src/client/views/search/FilterBox.tsx
+++ b/src/client/views/search/FilterBox.tsx
@@ -352,7 +352,6 @@ export class FilterBox extends React.Component {
     getDataStatus() { return this._deletedDocsStatus; }
 
     getActiveFilters() {
-        console.log(this._authorFieldStatus, this._titleFieldStatus, this._dataFieldStatus);
         return (
             <div className="active-filters">
                 {!this._basicWordStatus ? <div className="active-icon container">
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index c9d29e485..99fa6da21 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -125,7 +125,7 @@ export class SearchBox extends React.Component<SearchProps> {
             return returnedUri;
 
         } catch (e) {
-            console.log(e);
+            console.log("SearchBox:" + e);
         }
     }
 
@@ -582,7 +582,6 @@ export class SearchBox extends React.Component<SearchProps> {
     }
 
     expandSection(thing: string) {
-        console.log("expand");
         const element = document.getElementById(thing)!;
         // get the height of the element's inner content, regardless of its actual size
         const sectionHeight = element.scrollHeight;
@@ -593,7 +592,6 @@ export class SearchBox extends React.Component<SearchProps> {
         // when the next css transition finishes (which should be the one we just triggered)
         element.addEventListener('transitionend', function handler(e) {
             // remove this event listener so it only gets triggered once
-            console.log("autoset");
             element.removeEventListener('transitionend', handler);
 
             // remove "height" from the element's inline styles, so it can return to its initial value
@@ -608,7 +606,6 @@ export class SearchBox extends React.Component<SearchProps> {
 
     autoset(thing: string) {
         const element = document.getElementById(thing)!;
-        console.log("autoset");
         element.removeEventListener('transitionend', function (e) { });
 
         // remove "height" from the element's inline styles, so it can return to its initial value
diff --git a/src/client/views/search/ToggleBar.tsx b/src/client/views/search/ToggleBar.tsx
index e4d7f2fd5..466822eba 100644
--- a/src/client/views/search/ToggleBar.tsx
+++ b/src/client/views/search/ToggleBar.tsx
@@ -58,7 +58,6 @@ export class ToggleBar extends React.Component<ToggleBarProps>{
         this._forwardTimeline.play();
         this._forwardTimeline.reverse();
         this.props.handleChange();
-        console.log(this.props.getStatus());
     }
 
     @action.bound
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 917a6853c..7e91a7761 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -566,7 +566,6 @@ export namespace Doc {
     export async function Zip(doc: Doc) {
         const { clone, map } = await Doc.MakeClone(doc, true);
         function replacer(key: any, value: any) {
-            console.log("Checkin: " + key);
             if (["cloneOf", "context", "cursors"].includes(key)) return undefined;
             else if (value instanceof Doc) {
                 if (key !== "field" && Number.isNaN(Number(key))) {
diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts
index 4604a2132..bd08b2f32 100644
--- a/src/fields/ScriptField.ts
+++ b/src/fields/ScriptField.ts
@@ -53,7 +53,6 @@ async function deserializeScript(script: ScriptField) {
     if (script.script.originalScript === 'convertToButtons(dragData)') {
         return (script as any).script = (ScriptField.ConvertToButtons ?? (ScriptField.ConvertToButtons = ComputedField.MakeFunction('convertToButtons(dragData)', { dragData: "DocumentDragData" })))?.script;
     }
-    console.log(script.script.originalScript);
     const captures: ProxyField<Doc> = (script as any).captures;
     if (captures) {
         const doc = (await captures.value())!;
diff --git a/src/fields/util.ts b/src/fields/util.ts
index 20b072786..ef66d9633 100644
--- a/src/fields/util.ts
+++ b/src/fields/util.ts
@@ -35,7 +35,6 @@ export namespace Plugins {
 }
 
 const _setterImpl = action(function (target: any, prop: string | symbol | number, value: any, receiver: any): boolean {
-    //console.log("-set " + target[SelfProxy].title + "(" + target[SelfProxy][prop] + ")." + prop.toString() + " = " + value);
     if (SerializationHelper.IsSerializing()) {
         target[prop] = value;
         return true;
diff --git a/src/server/Recommender.ts b/src/server/Recommender.ts
index 423ce9b46..935ec3871 100644
--- a/src/server/Recommender.ts
+++ b/src/server/Recommender.ts
@@ -21,7 +21,6 @@
 //     private choice: string = ""; // Tensorflow or Word2Vec
 
 //     constructor() {
-//         console.log("creating recommender...");
 //         Recommender.Instance = this;
 //     }
 
@@ -70,7 +69,6 @@
 //         if (this._model) {
 //             if (this.choice === "WV") {
 //                 let similarity = this._model.similarity('father', 'mother');
-//                 console.log(similarity);
 //             }
 //             else if (this.choice === "TF") {
 //                 const model = this._model as use.UniversalSentenceEncoder;
@@ -119,7 +117,6 @@
 //     }
 
 //     // public async trainModel() {
-//     //     console.log("phrasing...");
 //     //     w2v.word2vec("./node_modules/word2vec/examples/eng_news-typical_2016_1M-sentences.txt", './node_modules/word2vec/examples/my_phrases.txt', {
 //     //         cbow: 1,
 //     //         size: 200,
@@ -131,7 +128,6 @@
 //     //         iter: 200,
 //     //         minCount: 2
 //     //     });
-//     //     console.log("phrased!!!");
 //     // }
 
 // }
diff --git a/src/server/downsize.ts b/src/server/downsize.ts
index cd0d83812..5cd709fa3 100644
--- a/src/server/downsize.ts
+++ b/src/server/downsize.ts
@@ -7,7 +7,7 @@ const jpgTypes = ["jpg", "JPG", "jpeg", "JPEG"];
 const smallResizer = sharp().resize(100);
 fs.readdir(folder, async (err, files) => {
     if (err) {
-        console.log(err);
+        console.log("readdir:" + err);
         return;
     }
     // files.forEach(file => {
-- 
cgit v1.2.3-70-g09d2

