From 866561aa20aff0f570d31edf64eae36cd2d35279 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 14 Jul 2020 17:27:19 -0400
Subject: fixed onClickHandler stuff to use functions properly.  fixed several
 linking to annotations/pushpins problems.

---
 src/client/views/MetadataEntryMenu.tsx | 96 +++++++++-------------------------
 1 file changed, 24 insertions(+), 72 deletions(-)

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

diff --git a/src/client/views/MetadataEntryMenu.tsx b/src/client/views/MetadataEntryMenu.tsx
index b0752ffb2..ca8a6e1d7 100644
--- a/src/client/views/MetadataEntryMenu.tsx
+++ b/src/client/views/MetadataEntryMenu.tsx
@@ -3,14 +3,14 @@ import "./MetadataEntryMenu.scss";
 import { observer } from 'mobx-react';
 import { observable, action, runInAction, trace, computed, IReactionDisposer, reaction } from 'mobx';
 import { KeyValueBox } from './nodes/KeyValueBox';
-import { Doc, Field, DocListCastAsync } from '../../fields/Doc';
+import { Doc, Field, DocListCastAsync, DocListCast } from '../../fields/Doc';
 import * as Autosuggest from 'react-autosuggest';
-import { undoBatch } from '../util/UndoManager';
+import { undoBatch, UndoManager } from '../util/UndoManager';
 import { emptyFunction, emptyPath } from '../../Utils';
 
 export type DocLike = Doc | Doc[] | Promise<Doc> | Promise<Doc[]>;
 export interface MetadataEntryProps {
-    docs: DocLike | (() => DocLike);
+    docs: Doc[];
     onError?: () => boolean;
     suggestWithFunction?: boolean;
 }
@@ -39,26 +39,13 @@ export class MetadataEntryMenu extends React.Component<MetadataEntryProps>{
         let onProto: boolean = false;
         let value: string | undefined = undefined;
         let docs = this.props.docs;
-        if (typeof docs === "function") {
-            if (this.props.suggestWithFunction) {
-                docs = docs();
-            } else {
-                return;
-            }
-        }
-        docs = await docs;
-        if (docs instanceof Doc) {
-            await docs[this._currentKey];
-            value = Field.toKeyValueString(docs, this._currentKey);
-        } else {
-            for (const doc of docs) {
-                const v = await doc[this._currentKey];
-                onProto = onProto || !Object.keys(doc).includes(this._currentKey);
-                if (field === null) {
-                    field = v;
-                } else if (v !== field) {
-                    value = "multiple values";
-                }
+        for (const doc of docs) {
+            const v = await doc[this._currentKey];
+            onProto = onProto || !Object.keys(doc).includes(this._currentKey);
+            if (field === null) {
+                field = v;
+            } else if (v !== field) {
+                value = "multiple values";
             }
         }
         if (value === undefined) {
@@ -86,27 +73,16 @@ export class MetadataEntryMenu extends React.Component<MetadataEntryProps>{
             const script = KeyValueBox.CompileKVPScript(this._currentValue);
             if (!script) return;
 
-            let doc = this.props.docs;
-            if (typeof doc === "function") {
-                doc = doc();
-            }
-            doc = await doc;
-
-            let success: boolean;
-            if (doc instanceof Doc) {
-                success = KeyValueBox.ApplyKVPScript(doc, this._currentKey, script);
-            } else {
-                let childSuccess = true;
-                if (this._addChildren) {
-                    for (const document of doc) {
-                        const collectionChildren = await DocListCastAsync(document.data);
-                        if (collectionChildren) {
-                            childSuccess = collectionChildren.every(c => KeyValueBox.ApplyKVPScript(c, this._currentKey, script));
-                        }
+            let childSuccess = true;
+            if (this._addChildren) {
+                for (const document of this.props.docs) {
+                    const collectionChildren = DocListCast(document.data);
+                    if (collectionChildren) {
+                        childSuccess = collectionChildren.every(c => KeyValueBox.ApplyKVPScript(c, this._currentKey, script));
                     }
                 }
-                success = doc.every(d => KeyValueBox.ApplyKVPScript(d, this._currentKey, script)) && childSuccess;
             }
+            const success = this.props.docs.every(d => KeyValueBox.ApplyKVPScript(d, this._currentKey, script)) && childSuccess;
             if (!success) {
                 if (this.props.onError) {
                     if (this.props.onError()) {
@@ -132,24 +108,12 @@ export class MetadataEntryMenu extends React.Component<MetadataEntryProps>{
         }
     }
 
-    getKeySuggestions = async (value: string): Promise<string[]> => {
+    getKeySuggestions = (value: string) => {
         value = value.toLowerCase();
         let docs = this.props.docs;
-        if (typeof docs === "function") {
-            if (this.props.suggestWithFunction) {
-                docs = docs();
-            } else {
-                return [];
-            }
-        }
-        docs = await docs;
-        if (docs instanceof Doc) {
-            return Object.keys(docs).filter(key => key.toLowerCase().startsWith(value));
-        } else {
-            const keys = new Set<string>();
-            docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key)));
-            return Array.from(keys).filter(key => key.toLowerCase().startsWith(value));
-        }
+        const keys = new Set<string>();
+        docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key)));
+        return Array.from(keys).filter(key => key.toLowerCase().startsWith(value));
     }
     getSuggestionValue = (suggestion: string) => suggestion;
 
@@ -157,9 +121,8 @@ export class MetadataEntryMenu extends React.Component<MetadataEntryProps>{
         return (null);
     }
     componentDidMount() {
-
         this._suggestionDispser = reaction(() => this._currentKey,
-            () => this.getKeySuggestions(this._currentKey).then(action((s: string[]) => this._allSuggestions = s)),
+            () => this._allSuggestions = this.getKeySuggestions(this._currentKey),
             { fireImmediately: true });
     }
     componentWillUnmount() {
@@ -171,19 +134,8 @@ export class MetadataEntryMenu extends React.Component<MetadataEntryProps>{
     }
 
     private get considerChildOptions() {
-        let docSource = this.props.docs;
-        if (typeof docSource === "function") {
-            docSource = docSource();
-        }
-        docSource = docSource as Doc[] | Doc;
-        if (docSource instanceof Doc) {
-            if (docSource._viewType === undefined) {
-                return (null);
-            }
-        } else if (Array.isArray(docSource)) {
-            if (!docSource.every(doc => doc._viewType !== undefined)) {
-                return null;
-            }
+        if (!this.props.docs.every(doc => doc._viewType !== undefined)) {
+            return null;
         }
         return (
             <div style={{ display: "flex" }}>
-- 
cgit v1.2.3-70-g09d2


From 12dd45618c0dc595b8e6663bf8d3635dd7161306 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 21 Jul 2020 16:02:53 -0400
Subject: fixed compile warnings

---
 src/client/documents/Documents.ts                             |  4 +++-
 src/client/util/DragManager.ts                                |  9 ++++-----
 src/client/views/DocumentDecorations.tsx                      | 11 +++++------
 src/client/views/MetadataEntryMenu.tsx                        |  4 ++--
 src/client/views/collections/CollectionMenu.tsx               |  6 +++---
 .../collectionFreeForm/CollectionFreeFormLinkView.tsx         | 10 +++++-----
 6 files changed, 22 insertions(+), 22 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 657ba521b..e2569ec70 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -550,7 +550,9 @@ export namespace Docs {
             const dataDoc = MakeDataDelegate(proto, protoProps, data, fieldKey);
             const viewDoc = Doc.MakeDelegate(dataDoc, delegId);
 
-            // so that the list of annotations is already initialised, prevents issues in addonly
+            // so that the list of annotations is already initialised, prevents issues in addonly.
+            // without this, if a doc has no annotations but the user has AddOnly privileges, they won't be able to add an annotation because they would have needed to create the field's list which they don't have permissions to do.
+
             dataDoc[fieldKey + "-annotations"] = new List<Doc>();
 
             proto.links = ComputedField.MakeFunction("links(self)");
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 4291eee9c..837f0b1db 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -412,7 +412,6 @@ export namespace DragManager {
         const yFromTop = downY - elesCont.top;
         const xFromRight = elesCont.right - downX;
         const yFromBottom = elesCont.bottom - downY;
-        let paused = false;
         let scrollAwaiter: Opt<NodeJS.Timeout>;
         const moveHandler = (e: PointerEvent) => {
             e.preventDefault(); // required or dragging text menu link item ends up dragging the link button as native drag/drop
@@ -437,8 +436,6 @@ export namespace DragManager {
             const target = document.elementFromPoint(e.x, e.y);
 
             if (target && !options?.noAutoscroll && !dragData.draggedDocuments?.some((d: any) => d._noAutoscroll)) {
-                scrollAwaiter && clearTimeout(scrollAwaiter);
-                scrollAwaiter = setTimeout(() => autoScrollHandler(), 250);
                 const autoScrollHandler = () => {
                     target.dispatchEvent(
                         new CustomEvent<React.DragEvent>("dashDragAutoScroll", {
@@ -483,8 +480,10 @@ export namespace DragManager {
                     );
 
                     scrollAwaiter && clearTimeout(scrollAwaiter);
-                    SnappingManager.GetIsDragging() && (scrollAwaiter = setTimeout(() => autoScrollHandler(), 25));
-                }
+                    SnappingManager.GetIsDragging() && (scrollAwaiter = setTimeout(autoScrollHandler, 25));
+                };
+                scrollAwaiter && clearTimeout(scrollAwaiter);
+                scrollAwaiter = setTimeout(autoScrollHandler, 250);
             }
 
             const { thisX, thisY } = snapDrag(e, xFromLeft, yFromTop, xFromRight, yFromBottom);
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 35c040f86..fec4ad9e0 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -293,13 +293,12 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             const doc = Document(element.rootDoc);
             if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) {
                 doc.rotation = Number(doc.rotation) + Number(angle);
-                const ink = Cast(doc.data, InkField)?.inkData;
-                if (ink) {
-
+                const inks = Cast(doc.data, InkField)?.inkData;
+                if (inks) {
                     const newPoints: { X: number, Y: number }[] = [];
-                    for (var i = 0; i < ink.length; i++) {
-                        const newX = Math.cos(angle) * (ink[i].X - this._centerPoints[index].X) - Math.sin(angle) * (ink[i].Y - this._centerPoints[index].Y) + this._centerPoints[index].X;
-                        const newY = Math.sin(angle) * (ink[i].X - this._centerPoints[index].X) + Math.cos(angle) * (ink[i].Y - this._centerPoints[index].Y) + this._centerPoints[index].Y;
+                    for (const ink of inks) {
+                        const newX = Math.cos(angle) * (ink.X - this._centerPoints[index].X) - Math.sin(angle) * (ink.Y - this._centerPoints[index].Y) + this._centerPoints[index].X;
+                        const newY = Math.sin(angle) * (ink.X - this._centerPoints[index].X) + Math.cos(angle) * (ink.Y - this._centerPoints[index].Y) + this._centerPoints[index].Y;
                         newPoints.push({ X: newX, Y: newY });
                     }
                     doc.data = new InkField(newPoints);
diff --git a/src/client/views/MetadataEntryMenu.tsx b/src/client/views/MetadataEntryMenu.tsx
index ca8a6e1d7..82ec5a5b3 100644
--- a/src/client/views/MetadataEntryMenu.tsx
+++ b/src/client/views/MetadataEntryMenu.tsx
@@ -38,7 +38,7 @@ export class MetadataEntryMenu extends React.Component<MetadataEntryProps>{
         let field: Field | undefined | null = null;
         let onProto: boolean = false;
         let value: string | undefined = undefined;
-        let docs = this.props.docs;
+        const docs = this.props.docs;
         for (const doc of docs) {
             const v = await doc[this._currentKey];
             onProto = onProto || !Object.keys(doc).includes(this._currentKey);
@@ -110,7 +110,7 @@ export class MetadataEntryMenu extends React.Component<MetadataEntryProps>{
 
     getKeySuggestions = (value: string) => {
         value = value.toLowerCase();
-        let docs = this.props.docs;
+        const docs = this.props.docs;
         const keys = new Set<string>();
         docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key)));
         return Array.from(keys).filter(key => key.toLowerCase().startsWith(value));
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 2be57b6d2..e7c5ca86b 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -402,7 +402,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
     }
 
     @computed get widthPicker() {
-        var widthPicker = this.toggleButton("stroke width", this._widthBtn, () => this._widthBtn = !this._widthBtn, "bars", null);
+        const widthPicker = this.toggleButton("stroke width", this._widthBtn, () => this._widthBtn = !this._widthBtn, "bars", null);
         return !this._widthBtn ? widthPicker :
             <div className="btn2-group" key="width">
                 {widthPicker}
@@ -416,7 +416,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
     }
 
     @computed get colorPicker() {
-        var colorPicker = this.toggleButton("stroke color", this._colorBtn, () => this._colorBtn = !this._colorBtn, "pen-nib",
+        const colorPicker = this.toggleButton("stroke color", this._colorBtn, () => this._colorBtn = !this._colorBtn, "pen-nib",
             <div className="color-previewI" style={{ backgroundColor: ActiveInkColor() ?? "121212" }} />);
         return !this._colorBtn ? colorPicker :
             <div className="btn-group" key="color">
@@ -431,7 +431,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
             </div>;
     }
     @computed get fillPicker() {
-        var fillPicker = this.toggleButton("shape fill color", this._fillBtn, () => this._fillBtn = !this._fillBtn, "fill-drip",
+        const fillPicker = this.toggleButton("shape fill color", this._fillBtn, () => this._fillBtn = !this._fillBtn, "fill-drip",
             <div className="color-previewI" style={{ backgroundColor: ActiveFillColor() ?? "121212" }} />);
         return !this._fillBtn ? fillPicker :
             <div className="btn-group" key="fill" >
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index 6d44ac967..bfe569853 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -26,7 +26,7 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
         this._anchorDisposer?.();
     }
     @action
-    timeout = () => (Date.now() < this._start++ + 1000) && setTimeout(this.timeout, 25);
+    timeout = () => (Date.now() < this._start++ + 1000) && setTimeout(this.timeout, 25)
     componentDidMount() {
         this._anchorDisposer = reaction(() => [this.props.A.props.ScreenToLocalTransform(), this.props.B.props.ScreenToLocalTransform(), this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document), this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document)],
             action(() => {
@@ -111,10 +111,10 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
             return undefined;
         }
         this.props.A.props.ScreenToLocalTransform().transform(this.props.B.props.ScreenToLocalTransform());
-        const acont = this.props.A.ContentDiv!.getElementsByClassName("linkAnchorBox-cont");
-        const bcont = this.props.B.ContentDiv!.getElementsByClassName("linkAnchorBox-cont");
-        const a = (acont.length ? acont[0] : this.props.A.ContentDiv!).getBoundingClientRect();
-        const b = (bcont.length ? bcont[0] : this.props.B.ContentDiv!).getBoundingClientRect();
+        const acont = this.props.A.ContentDiv.getElementsByClassName("linkAnchorBox-cont");
+        const bcont = this.props.B.ContentDiv.getElementsByClassName("linkAnchorBox-cont");
+        const a = (acont.length ? acont[0] : this.props.A.ContentDiv).getBoundingClientRect();
+        const b = (bcont.length ? bcont[0] : this.props.B.ContentDiv).getBoundingClientRect();
         const apt = Utils.closestPtBetweenRectangles(a.left, a.top, a.width, a.height,
             b.left, b.top, b.width, b.height,
             a.left + a.width / 2, a.top + a.height / 2);
-- 
cgit v1.2.3-70-g09d2

