From 2a313f28fcb8675223708b0657de7517a3281095 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 17 Apr 2024 12:27:21 -0400
Subject: restoring eslint - updates not complete yet

---
 src/client/views/collections/CollectionSubView.tsx | 173 +++++++++++++--------
 1 file changed, 104 insertions(+), 69 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 32198e3a2..cd401058f 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -1,10 +1,10 @@
 import { action, computed, makeObservable, observable } from 'mobx';
 import * as React from 'react';
 import * as rp from 'request-promise';
-import { Utils, returnFalse } from '../../../Utils';
+import { ClientUtils, returnFalse } from '../../../ClientUtils';
 import CursorField from '../../../fields/CursorField';
-import { Doc, DocListCast, Field, Opt, StrListCast } from '../../../fields/Doc';
-import { AclPrivate, DocData } from '../../../fields/DocSymbols';
+import { Doc, DocListCast, Field, FieldType, Opt, StrListCast } from '../../../fields/Doc';
+import { AclPrivate } from '../../../fields/DocSymbols';
 import { Id } from '../../../fields/FieldSymbols';
 import { List } from '../../../fields/List';
 import { listSpec } from '../../../fields/Schema';
@@ -15,16 +15,47 @@ import { GestureUtils } from '../../../pen-gestures/GestureUtils';
 import { DocServer } from '../../DocServer';
 import { Networking } from '../../Network';
 import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
-import { ViewBoxBaseComponent } from '../DocComponent';
 import { DocUtils, Docs, DocumentOptions } from '../../documents/Documents';
-import { DragManager, dropActionType } from '../../util/DragManager';
+import { DragManager } from '../../util/DragManager';
+import { dropActionType } from '../../util/DropActionTypes';
 import { ImageUtils } from '../../util/Import & Export/ImageUtils';
 import { SelectionManager } from '../../util/SelectionManager';
 import { SnappingManager } from '../../util/SnappingManager';
 import { UndoManager, undoBatch } from '../../util/UndoManager';
+import { ViewBoxBaseComponent } from '../DocComponent';
+import { FieldViewProps } from '../nodes/FieldView';
 import { LoadingBox } from '../nodes/LoadingBox';
 import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
-import { CollectionView, CollectionViewProps } from './CollectionView';
+
+export interface CollectionViewProps extends React.PropsWithChildren<FieldViewProps> {
+    isAnnotationOverlay?: boolean; // is the collection an annotation overlay (eg an overlay on an image/video/etc)
+    isAnnotationOverlayScrollable?: boolean; // whether the annotation overlay can be vertically scrolled (just for tree views, currently)
+    layoutEngine?: () => string;
+    setPreviewCursor?: (func: (x: number, y: number, drag: boolean, hide: boolean, doc: Opt<Doc>) => void) => void;
+    ignoreUnrendered?: boolean;
+
+    // property overrides for child documents
+    childDocuments?: Doc[]; // used to override the documents shown by the sub collection to an explicit list (see LinkBox)
+    childDocumentsActive?: () => boolean | undefined; // whether child documents can be dragged if collection can be dragged (eg., in a when a Pile document is in startburst mode)
+    childContentsActive?: () => boolean | undefined;
+    childLayoutFitWidth?: (child: Doc) => boolean;
+    childlayout_showTitle?: () => string;
+    childOpacity?: () => number;
+    childContextMenuItems?: () => { script: ScriptField; label: string }[];
+    childLayoutTemplate?: () => Doc | undefined; // specify a layout Doc template to use for children of the collection
+    childHideDecorationTitle?: boolean;
+    childHideResizeHandles?: boolean;
+    childDragAction?: dropActionType;
+    childXPadding?: number;
+    childYPadding?: number;
+    childLayoutString?: string;
+    childIgnoreNativeSize?: boolean;
+    childClickScript?: ScriptField;
+    childDoubleClickScript?: ScriptField;
+    AddToMap?: (treeViewDoc: Doc, index: number[]) => void;
+    RemFromMap?: (treeViewDoc: Doc, index: number[]) => void;
+    hierarchyIndex?: number[]; // hierarchical index of a document up to the rendering root (primarily used for tree views)
+}
 
 export interface SubCollectionViewProps extends CollectionViewProps {
     isAnyChildContentActive: () => boolean;
@@ -53,7 +84,7 @@ export function CollectionSubView<X>(moreProps?: X) {
             }
         };
         protected CreateDropTarget(ele: HTMLDivElement) {
-            //used in schema view
+            // used in schema view
             this.createDashEventsTarget(ele);
         }
 
@@ -83,10 +114,11 @@ export function CollectionSubView<X>(moreProps?: X) {
             const { Document, TemplateDataDocument } = this._props;
             const validPairs = this.childDocs
                 .map(doc => Doc.GetLayoutDataDocPair(Document, !this._props.isAnnotationOverlay ? TemplateDataDocument : undefined, doc))
-                .filter(pair => {
-                    // filter out any documents that have a proto that we don't have permissions to
-                    return !pair.layout?.hidden && pair.layout && (!pair.layout.proto || (pair.layout.proto instanceof Doc && GetEffectiveAcl(pair.layout.proto) !== AclPrivate));
-                });
+                .filter(
+                    pair =>
+                        // filter out any documents that have a proto that we don't have permissions to
+                        !pair.layout?.hidden && pair.layout && (!pair.layout.proto || (pair.layout.proto instanceof Doc && GetEffectiveAcl(pair.layout.proto) !== AclPrivate))
+                );
             return validPairs.map(({ data, layout }) => ({ data: data as Doc, layout: layout! })); // this mapping is a bit of a hack to coerce types
         }
         @computed get childDocList() {
@@ -95,9 +127,9 @@ export function CollectionSubView<X>(moreProps?: X) {
         collectionFilters = () => this._focusFilters ?? StrListCast(this.Document._childFilters);
         collectionRangeDocFilters = () => this._focusRangeFilters ?? Cast(this.Document._childFiltersByRanges, listSpec('string'), []);
         // child filters apply to the descendants of the documents in this collection
-        childDocFilters = () => [...(this._props.childFilters?.().filter(f => Utils.IsRecursiveFilter(f)) || []), ...this.collectionFilters()];
+        childDocFilters = () => [...(this._props.childFilters?.().filter(f => ClientUtils.IsRecursiveFilter(f)) || []), ...this.collectionFilters()];
         // unrecursive filters apply to the documents in the collection, but no their children.  See Utils.noRecursionHack
-        unrecursiveDocFilters = () => [...(this._props.childFilters?.().filter(f => !Utils.IsRecursiveFilter(f)) || [])];
+        unrecursiveDocFilters = () => [...(this._props.childFilters?.().filter(f => !ClientUtils.IsRecursiveFilter(f)) || [])];
         childDocRangeFilters = () => [...(this._props.childFiltersByRanges?.() || []), ...this.collectionRangeDocFilters()];
         searchFilterDocs = () => this._props.searchFilterDocs?.() ?? DocListCast(this.Document._searchFilterDocs);
         @computed.struct get childDocs() {
@@ -129,13 +161,13 @@ export function CollectionSubView<X>(moreProps?: X) {
             const docsforFilter: Doc[] = [];
             childDocs.forEach(d => {
                 // dragging facets
-                const dragged = this._props.childFilters?.().some(f => f.includes(Utils.noDragDocsFilter));
-                if (dragged && SnappingManager.CanEmbed && DragManager.docsBeingDragged.includes(d)) return false;
+                const dragged = this._props.childFilters?.().some(f => f.includes(ClientUtils.noDragDocsFilter));
+                if (dragged && SnappingManager.CanEmbed && DragManager.docsBeingDragged.includes(d)) return;
                 let notFiltered = d.z || Doc.IsSystem(d) || DocUtils.FilterDocs([d], this.unrecursiveDocFilters(), childFiltersByRanges, this.Document).length > 0;
                 if (notFiltered) {
                     notFiltered = (!searchDocs.length || searchDocs.includes(d)) && DocUtils.FilterDocs([d], childDocFilters, childFiltersByRanges, this.Document).length > 0;
                     const fieldKey = Doc.LayoutFieldKey(d);
-                    const annos = !Field.toString(Doc.LayoutField(d) as Field).includes(CollectionView.name);
+                    const annos = !Field.toString(Doc.LayoutField(d) as FieldType).includes(CollectionView.name);
                     const data = d[annos ? fieldKey + '_annotations' : fieldKey];
                     const side = annos && d[fieldKey + '_sidebar'];
                     if (data !== undefined || side !== undefined) {
@@ -147,7 +179,7 @@ export function CollectionSubView<X>(moreProps?: X) {
                                 newarray = [];
                                 subDocs.forEach(t => {
                                     const fieldKey = Doc.LayoutFieldKey(t);
-                                    const annos = !Field.toString(Doc.LayoutField(t) as Field).includes(CollectionView.name);
+                                    const annos = !Field.toString(Doc.LayoutField(t) as FieldType).includes(CollectionView.name);
                                     notFiltered =
                                         notFiltered || ((!searchDocs.length || searchDocs.includes(t)) && ((!childDocFilters.length && !childFiltersByRanges.length) || DocUtils.FilterDocs([t], childDocFilters, childFiltersByRanges, d).length));
                                     DocListCast(t[annos ? fieldKey + '_annotations' : fieldKey]).forEach(newdoc => newarray.push(newdoc));
@@ -168,7 +200,7 @@ export function CollectionSubView<X>(moreProps?: X) {
             let ind;
             const doc = this.Document;
             const id = Doc.UserDoc()[Id];
-            const email = Doc.CurrentUserEmail;
+            const email = ClientUtils.CurrentUserEmail;
             const pos = { x: position[0], y: position[1] };
             if (id && email) {
                 const proto = Doc.GetProto(doc);
@@ -184,6 +216,7 @@ export function CollectionSubView<X>(moreProps?: X) {
                 if (!cursors) {
                     proto.cursors = cursors = new List<CursorField>();
                 }
+                // eslint-disable-next-line no-cond-assign
                 if (cursors.length > 0 && (ind = cursors.findIndex(entry => entry.data.metadata.id === id)) > -1) {
                     cursors[ind].setPosition(pos);
                 } else {
@@ -215,9 +248,9 @@ export function CollectionSubView<X>(moreProps?: X) {
         moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[], annotationKey?: string) => boolean, annotationKey?: string) => this._props.moveDocument?.(doc, targetCollection, addDocument) || false;
 
         protected onInternalDrop(e: Event, de: DragManager.DropEvent): boolean {
-            const docDragData = de.complete.docDragData;
+            const { docDragData } = de.complete;
             if (docDragData) {
-                let added = undefined;
+                let added;
                 const dropAction = docDragData.dropAction || docDragData.userDropAction;
                 const targetDocments = DocListCast(this.dataDoc[this._props.fieldKey]);
                 const someMoved = !dropAction && docDragData.draggedDocuments.some(drag => targetDocments.includes(drag));
@@ -245,8 +278,9 @@ export function CollectionSubView<X>(moreProps?: X) {
                 }
                 added === false && !this._props.isAnnotationOverlay && e.preventDefault();
                 added === true && e.stopPropagation();
-                return added ? true : false;
-            } else if (de.complete.annoDragData) {
+                return !!added;
+            }
+            if (de.complete.annoDragData) {
                 const dropCreator = de.complete.annoDragData.dropDocCreator;
                 de.complete.annoDragData.dropDocCreator = () => {
                     const dropped = dropCreator(this._props.isAnnotationOverlay ? this.Document : undefined);
@@ -316,7 +350,7 @@ export function CollectionSubView<X>(moreProps?: X) {
                             const result = (await Networking.PostToServer('/uploadRemoteImage', { sources: [imgSrc] })).lastElement();
                             const newImgSrc =
                                 result.accessPaths.agnostic.client.indexOf('dashblobstore') === -1 //
-                                    ? Utils.prepend(result.accessPaths.agnostic.client)
+                                    ? ClientUtils.prepend(result.accessPaths.agnostic.client)
                                     : result.accessPaths.agnostic.client;
 
                             addDocument(ImageUtils.AssignImgInfo(Docs.Create.ImageDocument(newImgSrc, imgOpts), result));
@@ -325,39 +359,39 @@ export function CollectionSubView<X>(moreProps?: X) {
                             addDocument(ImageUtils.AssignImgInfo(doc, await ImageUtils.ExtractImgInfo(doc)));
                         }
                         return;
+                    }
+                    const path = window.location.origin + '/doc/';
+                    if (text.startsWith(path)) {
+                        const docId = text.replace(Doc.globalServerPath(), '').split('?')[0];
+                        DocServer.GetRefField(docId).then(f => {
+                            const fDoc = f;
+                            if (fDoc instanceof Doc) {
+                                if (options.x || options.y) {
+                                    fDoc.x = options.x as number;
+                                    fDoc.y = options.y as number;
+                                } // should be in CollectionFreeFormView
+                                addDocument(fDoc);
+                            }
+                        });
                     } else {
-                        const path = window.location.origin + '/doc/';
-                        if (text.startsWith(path)) {
-                            const docId = text.replace(Doc.globalServerPath(), '').split('?')[0];
-                            DocServer.GetRefField(docId).then(f => {
-                                if (f instanceof Doc) {
-                                    if (options.x || options.y) {
-                                        f.x = options.x as number;
-                                        f.y = options.y as number;
-                                    } // should be in CollectionFreeFormView
-                                    f instanceof Doc && addDocument(f);
-                                }
-                            });
-                        } else {
-                            const srcWeb = SelectionManager.Views.lastElement();
-                            const srcUrl = (srcWeb?.Document.data as WebField)?.url?.href?.match(/https?:\/\/[^/]*/)?.[0];
-                            const reg = new RegExp(Utils.prepend(''), 'g');
-                            const modHtml = srcUrl ? html.replace(reg, srcUrl) : html;
-                            const backgroundColor = tags.map(tag => tag.match(/.*(background-color: ?[^;]*)/)?.[1]?.replace(/background-color: ?(.*)/, '$1')).filter(t => t)?.[0];
-                            const htmlDoc = Docs.Create.HtmlDocument(modHtml, { ...options, title: srcUrl ? 'from:' + srcUrl : '-web clip-', _width: 300, _height: 300, backgroundColor });
-                            Doc.GetProto(htmlDoc)['data-text'] = Doc.GetProto(htmlDoc).text = text;
-                            addDocument(htmlDoc);
-                            if (srcWeb) {
-                                const iframe = SelectionManager.Views[0].ContentDiv?.getElementsByTagName('iframe')?.[0];
-                                const focusNode = iframe?.contentDocument?.getSelection()?.focusNode as any;
-                                if (focusNode) {
-                                    const anchor = srcWeb?.ComponentView?.getAnchor?.(true);
-                                    anchor && DocUtils.MakeLink(htmlDoc, anchor, {});
-                                }
+                        const srcWeb = SelectionManager.Views.lastElement();
+                        const srcUrl = (srcWeb?.Document.data as WebField)?.url?.href?.match(/https?:\/\/[^/]*/)?.[0];
+                        const reg = new RegExp(ClientUtils.prepend(''), 'g');
+                        const modHtml = srcUrl ? html.replace(reg, srcUrl) : html;
+                        const backgroundColor = tags.map(tag => tag.match(/.*(background-color: ?[^;]*)/)?.[1]?.replace(/background-color: ?(.*)/, '$1')).filter(t => t)?.[0];
+                        const htmlDoc = Docs.Create.HtmlDocument(modHtml, { ...options, title: srcUrl ? 'from:' + srcUrl : '-web clip-', _width: 300, _height: 300, backgroundColor });
+                        Doc.GetProto(htmlDoc)['data-text'] = Doc.GetProto(htmlDoc).text = text;
+                        addDocument(htmlDoc);
+                        if (srcWeb) {
+                            const iframe = SelectionManager.Views[0].ContentDiv?.getElementsByTagName('iframe')?.[0];
+                            const focusNode = iframe?.contentDocument?.getSelection()?.focusNode as any;
+                            if (focusNode) {
+                                const anchor = srcWeb?.ComponentView?.getAnchor?.(true);
+                                anchor && DocUtils.MakeLink(htmlDoc, anchor, {});
                             }
                         }
-                        return;
                     }
+                    return;
                 }
             }
 
@@ -414,10 +448,15 @@ export function CollectionSubView<X>(moreProps?: X) {
             for (let i = 0; i < length; i++) {
                 const item = e.dataTransfer.items[i];
                 if (item.kind === 'string' && item.type.includes('uri')) {
-                    const stringContents = await new Promise<string>(resolve => item.getAsString(resolve));
-                    const type = (await rp.head(Utils.CorsProxy(stringContents)))['content-type'];
+                    // eslint-disable-next-line no-await-in-loop
+                    const stringContents = await new Promise<string>(resolve => {
+                        item.getAsString(resolve);
+                    });
+                    // eslint-disable-next-line no-await-in-loop
+                    const type = (await rp.head(ClientUtils.CorsProxy(stringContents)))['content-type'];
                     if (type) {
-                        const doc = await DocUtils.DocumentFromType(type, Utils.CorsProxy(stringContents), options);
+                        // eslint-disable-next-line no-await-in-loop
+                        const doc = await DocUtils.DocumentFromType(type, ClientUtils.CorsProxy(stringContents), options);
                         doc && generatedDocuments.push(doc);
                     }
                 }
@@ -426,7 +465,7 @@ export function CollectionSubView<X>(moreProps?: X) {
                     file?.type && files.push(file);
 
                     file?.type === 'application/json' &&
-                        Utils.readUploadedFileAsText(file).then(result => {
+                        ClientUtils.readUploadedFileAsText(file).then(result => {
                             const json = JSON.parse(result as string);
                             addDocument(
                                 Docs.Create.TreeDocument(
@@ -450,7 +489,7 @@ export function CollectionSubView<X>(moreProps?: X) {
             // create placeholder docs
             // inside placeholder docs have some func that
 
-            let pileUpDoc = undefined;
+            let pileUpDoc;
             if (typeof files === 'string') {
                 const loading = Docs.Create.LoadingDocument(files, options);
                 generatedDocuments.push(loading);
@@ -478,20 +517,16 @@ export function CollectionSubView<X>(moreProps?: X) {
                         })
                       : [];
                 if (completed) completed(set);
-                else {
-                    if (isFreeformView && generatedDocuments.length > 1) {
-                        pileUpDoc = DocUtils.pileup(generatedDocuments, options.x as number, options.y as number)!;
-                        addDocument(pileUpDoc);
-                    } else {
-                        generatedDocuments.forEach(addDocument);
-                    }
-                }
-            } else {
-                if (text && !text.includes('https://')) {
-                    addDocument(Docs.Create.TextDocument(text, { ...options, title: text.substring(0, 20), _width: 400, _height: 315 }));
+                else if (isFreeformView && generatedDocuments.length > 1) {
+                    pileUpDoc = DocUtils.pileup(generatedDocuments, options.x as number, options.y as number)!;
+                    addDocument(pileUpDoc);
                 } else {
-                    alert('Document upload failed - possibly an unsupported file type.');
+                    generatedDocuments.forEach(addDocument);
                 }
+            } else if (text && !text.includes('https://')) {
+                addDocument(Docs.Create.TextDocument(text, { ...options, title: text.substring(0, 20), _width: 400, _height: 315 }));
+            } else {
+                alert('Document upload failed - possibly an unsupported file type.');
             }
         };
     }
-- 
cgit v1.2.3-70-g09d2

