From 205fdacf9807be2691e13e1d9d04d6b98620391a Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 15 Jan 2025 13:03:59 -0500
Subject: fixed so that users are sentt to dropbox to authorized uploads once,
 and then a refresh token is used afterwards.  fixed up some collection views
 to work better with the tagsView.  fixed grid view to show entire image. 
 tweaked notetaking view to work better with tags, but it's incomplete.

---
 src/client/views/collections/CollectionNoteTakingView.tsx | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

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

diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index ac8e37358..323a679cc 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -2,7 +2,7 @@ import { action, computed, IReactionDisposer, makeObservable, observable, reacti
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { ClientUtils, DivHeight, lightOrDark, returnZero, smoothScroll } from '../../../ClientUtils';
-import { Doc, Field, FieldType, Opt } from '../../../fields/Doc';
+import { Doc, Field, FieldType, Opt, StrListCast } from '../../../fields/Doc';
 import { DocData } from '../../../fields/DocSymbols';
 import { Copy, Id } from '../../../fields/FieldSymbols';
 import { List } from '../../../fields/List';
@@ -48,6 +48,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
     @computed get notetakingCategoryField() {
         return StrCast(this.dataDoc.notetaking_column, StrCast(this.layoutDoc.pivotField, 'notetaking_column'));
     }
+    toHeader = (d: Doc) => (d[this.notetakingCategoryField] instanceof List ? StrListCast(d[this.notetakingCategoryField]).join('.') : (d[this.notetakingCategoryField] ?? 'unset'));
     public DividerWidth = 16;
     @observable docsDraggedRowCol: number[] = [];
     @observable _scroll = 0;
@@ -136,7 +137,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
         const rowCol = this.docsDraggedRowCol;
         // this will sort the docs into the correct columns (minus the ones you're currently dragging)
         docs.forEach(d => {
-            const sectionValue = (d[this.notetakingCategoryField] as object) ?? `unset`;
+            const sectionValue = this.toHeader(d);
             // look for if header exists already
             const existingHeader = columnHeaders.find(sh => sh.heading === sectionValue.toString());
             if (existingHeader) {
@@ -161,7 +162,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
     };
 
     @computed get allFieldValues() {
-        return new Set(this.childDocs.map(doc => StrCast(doc[this.notetakingCategoryField])));
+        return new Set(this.childDocs.map(doc => (doc[this.notetakingCategoryField] instanceof List ? StrListCast(doc[this.notetakingCategoryField]).join('.') : StrCast(doc[this.notetakingCategoryField]))));
     }
 
     componentDidMount() {
@@ -313,7 +314,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
     // how to get the width of a document. Currently returns the width of the column (minus margins)
     // if a note doc. Otherwise, returns the normal width (for graphs, images, etc...)
     getDocWidth = (d: Doc) => {
-        const heading = !d[this.notetakingCategoryField] ? 'unset' : Field.toString(d[this.notetakingCategoryField] as FieldType);
+        const heading = this.toHeader(d);
         const existingHeader = this.colHeaderData.find(sh => sh.heading === heading);
         const existingWidth = this.layoutDoc._notetaking_columns_autoSize ? 1 / (this.colHeaderData.length ?? 1) : existingHeader?.width ? existingHeader.width : 0;
         const maxWidth = existingWidth > 0 ? existingWidth * this.availableWidth : this.maxColWidth;
@@ -427,7 +428,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
         const colHeader = colIndex === undefined ? 'unset' : StrCast(this.colHeaderData[colIndex].heading);
         this.childDocs?.forEach(d => {
             if (d instanceof Promise) return;
-            const sectionValue = (d[this.notetakingCategoryField] as object) ?? 'unset';
+            const sectionValue = this.toHeader(d);
             if (sectionValue.toString() === colHeader) {
                 docsMatchingHeader.push(d);
             }
-- 
cgit v1.2.3-70-g09d2


From 132fb0c203f426c508eeb23dd33b508e0608d19f Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 10 Feb 2025 09:38:32 -0500
Subject: code cleanup in createDocumentTool. added childLayoutFitWidth to
 comparisonBox so flashcards can fill window.

---
 src/ClientUtils.ts                                 |  9 ++++++
 .../views/collections/CollectionNoteTakingView.tsx |  2 +-
 src/client/views/nodes/ComparisonBox.tsx           |  6 ++--
 src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx |  2 --
 .../views/nodes/chatbot/agentsystem/Agent.ts       |  2 +-
 .../nodes/chatbot/tools/CreateDocumentTool.ts      | 25 ++++-----------
 src/client/views/nodes/trails/PresBox.tsx          |  1 -
 src/server/ApiManagers/AssistantManager.ts         | 37 ++++++++++++----------
 8 files changed, 43 insertions(+), 41 deletions(-)

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

diff --git a/src/ClientUtils.ts b/src/ClientUtils.ts
index e5dbb81db..8c9dd0a32 100644
--- a/src/ClientUtils.ts
+++ b/src/ClientUtils.ts
@@ -365,6 +365,15 @@ export namespace ClientUtils {
     }
 }
 
+/**
+ * Removes specified keys from an object and returns the result in the 'omit' field of the return value.
+ * The keys that were removed ared retuned in the 'extract' field of the return value.
+ * @param obj  - object to remove keys from
+ * @param keys - list of key field names to remove
+ * @param pattern - optional pattern to specify keys to removed
+ * @param addKeyFunc - optional function to call with object after keys have been removed
+ * @returns a tuple object containint 'omit' (oject after keys have been removed) and 'extact' (object containing omitted fields)
+ */
 export function OmitKeys(obj: object, keys: string[], pattern?: string, addKeyFunc?: (dup: object) => void): { omit: { [key: string]: unknown }; extract: { [key: string]: unknown } } {
     const omit: { [key: string]: unknown } = { ...obj };
     const extract: { [key: string]: unknown } = {};
diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index 323a679cc..4c23d4c48 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -2,7 +2,7 @@ import { action, computed, IReactionDisposer, makeObservable, observable, reacti
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { ClientUtils, DivHeight, lightOrDark, returnZero, smoothScroll } from '../../../ClientUtils';
-import { Doc, Field, FieldType, Opt, StrListCast } from '../../../fields/Doc';
+import { Doc, Opt, StrListCast } from '../../../fields/Doc';
 import { DocData } from '../../../fields/DocSymbols';
 import { Copy, Id } from '../../../fields/FieldSymbols';
 import { List } from '../../../fields/List';
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx
index 53fbd11c5..cb0831d3c 100644
--- a/src/client/views/nodes/ComparisonBox.tsx
+++ b/src/client/views/nodes/ComparisonBox.tsx
@@ -10,7 +10,7 @@ import { emptyFunction } from '../../../Utils';
 import { Doc, Opt } from '../../../fields/Doc';
 import { Animation, DocData } from '../../../fields/DocSymbols';
 import { RichTextField } from '../../../fields/RichTextField';
-import { BoolCast, DocCast, NumCast, RTFCast, StrCast, toList } from '../../../fields/Types';
+import { BoolCast, Cast, DocCast, NumCast, RTFCast, StrCast, toList } from '../../../fields/Types';
 import { nullAudio } from '../../../fields/URLField';
 import { GPTCallType, gptAPICall, gptImageLabel } from '../../apis/gpt/GPT';
 import { DocUtils, FollowLinkScript } from '../../documents/DocUtils';
@@ -677,6 +677,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
             </div>
         </Tooltip>
     );
+    childFitWidth = () => Cast(this.Document.childLayoutFitWidth, 'boolean') ?? Cast(this.Document.childLayoutFitWidth, 'boolean');
+
     displayDoc = (whichSlot: string) => {
         const whichDoc = DocCast(this.dataDoc[whichSlot]);
         const targetDoc = DocCast(whichDoc?.annotationOn, whichDoc);
@@ -696,7 +698,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
                     isDocumentActive={returnFalse}
                     isContentActive={this.childActiveFunc}
                     showTags={undefined}
-                    fitWidth={undefined} // set to returnTrue to make images fill the comparisonBox-- should be a user option
+                    fitWidth={this.childFitWidth} // set to returnTrue to make images fill the comparisonBox-- should be a user option
                     ignoreUsePath={layoutString ? true : undefined}
                     moveDocument={whichSlot === this.frontKey ? this.moveDocFront : this.moveDocBack}
                     removeDocument={whichSlot === this.frontKey ? this.remDocFront : this.remDocBack}
diff --git a/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx b/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx
index c69cd8e89..eb0431b85 100644
--- a/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx
+++ b/src/client/views/nodes/MapBox/MapBoxInfoWindow.tsx
@@ -41,7 +41,6 @@
 //     };
 
 //     _stack: CollectionStackingView | CollectionNoteTakingView | null | undefined;
-//     childLayoutFitWidth = (doc: Doc) => doc.type === DocumentType.RTF;
 //     addDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((p, d) => p && Doc.AddDocToList(this.props.place, 'data', d), true as boolean);
 //     removeDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((p, d) => p && Doc.RemoveDocFromList(this.props.place, 'data', d), true as boolean);
 //     render() {
@@ -69,7 +68,6 @@
 //                             chromeHidden={true}
 //                             childHideResizeHandles={true}
 //                             childHideDecorationTitle={true}
-//                             childLayoutFitWidth={this.childLayoutFitWidth}
 //                             // childDocumentsActive={returnFalse}
 //                             removeDocument={this.removeDoc}
 //                             addDocument={this.addDoc}
diff --git a/src/client/views/nodes/chatbot/agentsystem/Agent.ts b/src/client/views/nodes/chatbot/agentsystem/Agent.ts
index 25e471ce8..13fdac7f5 100644
--- a/src/client/views/nodes/chatbot/agentsystem/Agent.ts
+++ b/src/client/views/nodes/chatbot/agentsystem/Agent.ts
@@ -54,7 +54,7 @@ export class Agent {
         history: () => string,
         csvData: () => { filename: string; id: string; text: string }[],
         addLinkedUrlDoc: (url: string, id: string) => void,
-        addLinkedDoc: (doc_type: supportedDocumentTypes, data: unknown, options: DocumentOptions, id: string) => void,
+        addLinkedDoc: (doc_type: supportedDocumentTypes, data: unknown, options: DocumentOptions, id?: string) => void,
         // eslint-disable-next-line @typescript-eslint/no-unused-vars
         createCSVInDash: (url: string, title: string, id: string, data: string) => void
     ) {
diff --git a/src/client/views/nodes/chatbot/tools/CreateDocumentTool.ts b/src/client/views/nodes/chatbot/tools/CreateDocumentTool.ts
index b919b242c..07b515fea 100644
--- a/src/client/views/nodes/chatbot/tools/CreateDocumentTool.ts
+++ b/src/client/views/nodes/chatbot/tools/CreateDocumentTool.ts
@@ -1,8 +1,8 @@
-import { v4 as uuidv4 } from 'uuid';
 import { BaseTool } from './BaseTool';
 import { Observation } from '../types/types';
 import { ParametersType } from '../types/tool_types';
 import { DocumentOptions } from '../../../../documents/Documents';
+import { OmitKeys } from '../../../../../ClientUtils';
 
 export enum supportedDocumentTypes {
     flashcard = 'flashcard',
@@ -360,9 +360,9 @@ type CreateListDocToolParamsType = typeof createListDocToolParams;
 
 // Tool class for creating documents
 export class CreateDocTool extends BaseTool<CreateListDocToolParamsType> {
-    private _addLinkedDoc: (doc_type: supportedDocumentTypes, data: unknown, options: DocumentOptions, id: string) => void;
+    private _addLinkedDoc: (doc_type: supportedDocumentTypes, data: unknown, options: DocumentOptions) => void;
 
-    constructor(addLinkedDoc: (doc_type: supportedDocumentTypes, data: unknown, options: DocumentOptions, id: string) => void) {
+    constructor(addLinkedDoc: (doc_type: supportedDocumentTypes, data: unknown, options: DocumentOptions) => void) {
         super(
             'createDoc',
             `Creates one or more documents that best fit the user’s request. 
@@ -395,24 +395,13 @@ export class CreateDocTool extends BaseTool<CreateListDocToolParamsType> {
     async execute(args: ParametersType<CreateListDocToolParamsType>): Promise<Observation[]> {
         try {
             const parsedDoc = JSON.parse(args.docs) as ({ doc_type: supportedDocumentTypes; data: unknown } & DocumentOptions)[];
-            parsedDoc.forEach(doc =>
+            parsedDoc.forEach(
+                doc =>
                 this._addLinkedDoc(
                     doc.doc_type,
                     doc.data,
-                    {
-                        title: doc.title,
-                        backgroundColor: doc.backgroundColor,
-                        text_fontColor: doc.text_fontColor,
-                        _width: doc._width,
-                        _height: doc._height,
-                        type_collection: doc.type_collection,
-                        _layout_fitWidth: false,
-                        _layout_autoHeight: true,
-                        x: doc.x,
-                        y: doc.y,
-                    },
-                    uuidv4()
-                )
+                    {...OmitKeys(doc, ["data", "doc_type"]).omit, _layout_fitWidth: false, _layout_autoHeight: true}
+                ) // prettier-ignore
             );
             return [{ type: 'text', text: 'Created document.' }];
         } catch (error) {
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 7c23ca8e1..3ce4dc6cb 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -2989,7 +2989,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                 ignoreUnrendered
                                 childDragAction={dropActionType.move}
                                 setContentViewBox={emptyFunction}
-                                // childLayoutFitWidth={returnTrue}
                                 childOpacity={returnOne}
                                 childClickScript={PresBox.navigateToDocScript}
                                 childLayoutTemplate={this.childLayoutTemplate}
diff --git a/src/server/ApiManagers/AssistantManager.ts b/src/server/ApiManagers/AssistantManager.ts
index b53581aa2..86af756a4 100644
--- a/src/server/ApiManagers/AssistantManager.ts
+++ b/src/server/ApiManagers/AssistantManager.ts
@@ -9,7 +9,7 @@
  */
 
 import { Readability } from '@mozilla/readability';
-import axios, { AxiosResponse } from 'axios';
+import axios from 'axios';
 import { spawn } from 'child_process';
 import * as fs from 'fs';
 import { writeFile } from 'fs';
@@ -122,8 +122,6 @@ export default class AssistantManager extends ApiManager {
                 const { query, max_results } = req.body;
                 const MIN_VALID_RESULTS_RATIO = 0.75; // 3/4 threshold
                 let startIndex = 1; // Start at the first result initially
-                let validResults: any[] = [];
-
                 const fetchSearchResults = async (start: number) => {
                     return customsearch.cse.list({
                         q: query,
@@ -135,20 +133,27 @@ export default class AssistantManager extends ApiManager {
                     });
                 };
 
-                const filterResultsByXFrameOptions = async (results: any[]) => {
+                const filterResultsByXFrameOptions = async (
+                    results: {
+                        url: string | null | undefined;
+                        snippet: string | null | undefined;
+                    }[]
+                ) => {
                     const filteredResults = await Promise.all(
-                        results.map(async result => {
-                            try {
-                                const urlResponse: AxiosResponse = await axios.head(result.url, { timeout: 5000 });
-                                const xFrameOptions = urlResponse.headers['x-frame-options'];
-                                if (xFrameOptions && xFrameOptions.toUpperCase() === 'SAMEORIGIN') {
-                                    return result;
+                        results
+                            .filter(result => result.url)
+                            .map(async result => {
+                                try {
+                                    const urlResponse = await axios.head(result.url!, { timeout: 5000 });
+                                    const xFrameOptions = urlResponse.headers['x-frame-options'];
+                                    if (xFrameOptions && xFrameOptions.toUpperCase() === 'SAMEORIGIN') {
+                                        return result;
+                                    }
+                                } catch (error) {
+                                    console.error(`Error checking x-frame-options for URL: ${result.url}`, error);
                                 }
-                            } catch (error) {
-                                console.error(`Error checking x-frame-options for URL: ${result.url}`, error);
-                            }
-                            return null; // Exclude the result if it doesn't match
-                        })
+                                return null; // Exclude the result if it doesn't match
+                            })
                     );
                     return filteredResults.filter(result => result !== null); // Remove null results
                 };
@@ -163,7 +168,7 @@ export default class AssistantManager extends ApiManager {
                         })) || [];
 
                     // Filter the initial results
-                    validResults = await filterResultsByXFrameOptions(initialResults);
+                    let validResults = await filterResultsByXFrameOptions(initialResults);
 
                     // If valid results are less than 3/4 of max_results, fetch more results
                     while (validResults.length < max_results * MIN_VALID_RESULTS_RATIO) {
-- 
cgit v1.2.3-70-g09d2

