From 6f60b3ccf18c35c3faada44ef7187f4ae9d50ab1 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 13 Feb 2025 23:50:03 -0500
Subject: from last

---
 src/client/views/pdf/GPTPopup/GPTPopup.tsx | 119 ++++++++++++++---------------
 1 file changed, 57 insertions(+), 62 deletions(-)

(limited to 'src/client/views/pdf/GPTPopup/GPTPopup.tsx')

diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
index 691c24792..4457bde91 100644
--- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx
+++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
@@ -21,14 +21,12 @@ import { AnchorMenu } from '../AnchorMenu';
 import './GPTPopup.scss';
 
 export enum GPTPopupMode {
-    SUMMARY,
-    EDIT,
-    IMAGE,
-    FLASHCARD,
+    SUMMARY, // summary of seleted document text
+    IMAGE, // generate image from image description
     DATA,
-    CARD,
-    SORT,
-    QUIZ,
+    GPT_MENU, // menu for choosing type of prompts user will provide
+    USER_PROMPT, // user prompts for sorting,filtering and asking about docs
+    QUIZ_RESPONSE, // user definitions or explanations to be evaluated by GPT
 }
 
 export enum GPTQuizType {
@@ -50,10 +48,9 @@ export class GPTPopup extends ObservableReactComponent<object> {
     private _dataJson: string = '';
     private _sortDesc: string = '';
     private _sidebarFieldKey: string = '';
-    private _imgDesc: string = '';
     private _selectedText: string = '';
+    private _imgDesc: string = '';
 
-    public setImgDesc = (text: string) => (this._imgDesc = text);
     public setSidebarFieldKey = (id: string) => (this._sidebarFieldKey = id);
     public setSortDesc = (t: string) => (this._sortDesc = t);
     public setImgTargetDoc = (anchor: Doc) => (this._imgTargetDoc = anchor);
@@ -89,8 +86,8 @@ export class GPTPopup extends ObservableReactComponent<object> {
     @action public setMode = (mode: GPTPopupMode) => (this._mode = mode);
     @observable private _collectionContext: Doc | undefined = undefined;
     @action setCollectionContext = (doc: Doc | undefined) => (this._collectionContext = doc);
-    @observable private _sortPrompt: string = '';
-    @action setSortPrompt = (e: React.ChangeEvent<HTMLInputElement>) => (this._sortPrompt = e.target.value);
+    @observable private _userPrompt: string = '';
+    @action setUserPrompt = (e: React.ChangeEvent<HTMLInputElement>) => (this._userPrompt = e.target.value);
     @observable private _quizAnswer: string = '';
     @action setQuizAnswer = (e: React.ChangeEvent<HTMLInputElement>) => (this._quizAnswer = e.target.value);
     @observable private _stopAnimatingResponse: boolean = false;
@@ -149,7 +146,7 @@ export class GPTPopup extends ObservableReactComponent<object> {
      * Generates a response to the user's question depending on the type of their question
      * @param userPrompt the user's input that chat will respond to
      */
-    generateQueryResponse = (userPrompt: string) =>
+    generateUserPromptResponse = (userPrompt: string) =>
         (this._regenerateCallback ?? Promise.resolve)().then(() =>
             gptAPICall(userPrompt, GPTCallType.TYPE).then(questionType =>
                 (() => {
@@ -176,26 +173,24 @@ export class GPTPopup extends ObservableReactComponent<object> {
     /**
      * Generates a Dalle image and uploads it to the server.
      */
-    generateImage = () => {
-        if (this._imgDesc !== '') {
-            this.setImgUrls([]);
-            this.setMode(GPTPopupMode.IMAGE);
-            this.setVisible(true);
-            this.setGptProcessing(true);
-
-            return gptImageCall(this._imgDesc)
-                .then(imageUrls =>
-                    imageUrls?.[0]
-                        ? Networking.PostToServer('/uploadRemoteImage', { sources: [imageUrls[0]] }).then(res => {
-                              const source = ClientUtils.prepend(res[0].accessPaths.agnostic.client);
-                              return this.setImgUrls([[imageUrls[0]!, source]]);
-                          })
-                        : undefined
-                )
-                .catch(err => console.error(err))
-                .finally(() => this.setGptProcessing(false));
-        }
-        return undefined;
+    generateImage = (imgDesc: string) => {
+        this.setImgUrls([]);
+        this.setMode(GPTPopupMode.IMAGE);
+        this.setVisible(true);
+        this.setGptProcessing(true);
+        this._imgDesc = imgDesc;
+
+        return gptImageCall(imgDesc)
+            .then(imageUrls =>
+                imageUrls?.[0]
+                    ? Networking.PostToServer('/uploadRemoteImage', { sources: [imageUrls[0]] }).then(res => {
+                          const source = ClientUtils.prepend(res[0].accessPaths.agnostic.client);
+                          return this.setImgUrls([[imageUrls[0]!, source]]);
+                      })
+                    : undefined
+            )
+            .catch(err => console.error(err))
+            .finally(() => this.setGptProcessing(false));
     };
 
     /**
@@ -203,12 +198,12 @@ export class GPTPopup extends ObservableReactComponent<object> {
      *
      * @param text the text to summarizz
      */
-    generateSummary = (text?: string) => {
-        this._selectedText = text ?? this._selectedText;
+    generateSummary = (text: string) => {
+        this._selectedText = text;
         this.setVisible(true);
         this.setMode(GPTPopupMode.SUMMARY);
         this.setGptProcessing(true);
-        return gptAPICall(this._selectedText, GPTCallType.SUMMARY)
+        return gptAPICall(text, GPTCallType.SUMMARY)
             .then(res => this.setResponseText(res || 'Something went wrong.'))
             .catch(err => console.error(err))
             .finally(() => this.setGptProcessing(false));
@@ -286,12 +281,12 @@ export class GPTPopup extends ObservableReactComponent<object> {
 
     scrollToBottom = () => setTimeout(() => this._messagesEndRef.current?.scrollIntoView({ behavior: 'smooth', block: 'end' }), 50);
 
-    cardMenu = () => (
+    gptMenu = () => (
         <div className="btns-wrapper-gpt">
             <Button
-                tooltip="Have ChatGPT sort, tag, define, or filter your cards for you!"
+                tooltip="Have ChatGPT sort, tag, define, or filter your documents for you!"
                 text="Modify/Sort Cards!"
-                onClick={() => this.setMode(GPTPopupMode.SORT)}
+                onClick={() => this.setMode(GPTPopupMode.USER_PROMPT)}
                 color={StrCast(Doc.UserDoc().userVariantColor)}
                 type={Type.TERT}
                 style={{
@@ -308,7 +303,7 @@ export class GPTPopup extends ObservableReactComponent<object> {
                 text="Quiz Cards!"
                 onClick={() => {
                     this._conversationArray = ['Define the selected card!'];
-                    this.setMode(GPTPopupMode.QUIZ);
+                    this.setMode(GPTPopupMode.QUIZ_RESPONSE);
                     this.onQuizRandom?.();
                 }}
                 color={StrCast(Doc.UserDoc().userVariantColor)}
@@ -325,14 +320,14 @@ export class GPTPopup extends ObservableReactComponent<object> {
     );
 
     @action
-    handleKeyPress = async (e: React.KeyboardEvent, isSort: boolean) => {
+    handleKeyPress = async (e: React.KeyboardEvent, isUserPrompt: boolean) => {
         if (e.key === 'Enter') {
             e.stopPropagation();
 
             this.setGptProcessing(true);
-            if (isSort) {
-                this._conversationArray.push(this._sortPrompt);
-                await this.generateQueryResponse(this._sortPrompt).then(action(() => (this._sortPrompt = '')));
+            if (isUserPrompt) {
+                this._conversationArray.push(this._userPrompt);
+                await this.generateUserPromptResponse(this._userPrompt).then(action(() => (this._userPrompt = '')));
             } else {
                 this._conversationArray.push(this._quizAnswer);
                 await this.generateQuizAnswerAnalysis(DocumentView.SelectedDocs().lastElement(), this._quizAnswer).then(action(() => (this._quizAnswer = '')));
@@ -343,7 +338,7 @@ export class GPTPopup extends ObservableReactComponent<object> {
         }
     };
 
-    cardActual = (isSort: boolean) => (
+    gptUserInput = (isUserPrompt: boolean) => (
         <div className="btns-wrapper-gpt">
             <div className="chat-wrapper">
                 <div className="chat-bubbles">
@@ -352,7 +347,7 @@ export class GPTPopup extends ObservableReactComponent<object> {
                             {message}
                         </div>
                     ))}
-                    {this._gptProcessing && <div className={`chat-bubble chat-message`}>...</div>}
+                    {this._gptProcessing && <div className="chat-bubble chat-message">...</div>}
                 </div>
 
                 <div ref={this._messagesEndRef} style={{ height: '100px' }} />
@@ -361,21 +356,21 @@ export class GPTPopup extends ObservableReactComponent<object> {
                 <input
                     className="searchBox-input"
                     defaultValue=""
-                    value={isSort ? this._sortPrompt : this._quizAnswer} // Controlled input
+                    value={isUserPrompt ? this._userPrompt : this._quizAnswer} // Controlled input
                     autoComplete="off"
-                    onChange={isSort ? this.setSortPrompt : this.setQuizAnswer}
-                    onKeyDown={e => this.handleKeyPress(e, isSort)}
+                    onChange={isUserPrompt ? this.setUserPrompt : this.setQuizAnswer}
+                    onKeyDown={e => this.handleKeyPress(e, isUserPrompt)}
                     type="text"
-                    placeholder={`${isSort ? 'Have ChatGPT sort, tag, define, or filter your cards for you!' : 'Define the selected card!'}`}
+                    placeholder={`${isUserPrompt ? 'Have ChatGPT sort, tag, define, or filter your documents for you!' : 'Describe/answer the selected document!'}`}
                 />
             </div>
         </div>
     );
 
-    sortBox = (isSort: boolean) => (
+    promptBox = (isUserPrompt: boolean) => (
         <div className="gptPopup-sortBox" style={{ height: '80%' }}>
-            {this.heading(isSort ? 'SORTING' : 'QUIZ')}
-            {this._mode === GPTPopupMode.CARD ? this.cardMenu() : this.cardActual(isSort)}
+            {this.heading(isUserPrompt ? 'SORTING' : 'QUIZ')}
+            {this._mode === GPTPopupMode.GPT_MENU ? this.gptMenu() : this.gptUserInput(isUserPrompt)}
         </div>
     );
 
@@ -394,7 +389,7 @@ export class GPTPopup extends ObservableReactComponent<object> {
                     </div>
                 ))}
             </div>
-            {this._gptProcessing ? null : <IconButton tooltip="Generate Again" onClick={this.generateImage} icon={<FontAwesomeIcon icon="redo-alt" size="lg" />} color={StrCast(Doc.UserDoc().userVariantColor)} />}
+            {this._gptProcessing ? null : <IconButton tooltip="Generate Again" onClick={() => this.generateImage(this._imgDesc)} icon={<FontAwesomeIcon icon="redo-alt" size="lg" />} color={StrCast(Doc.UserDoc().userVariantColor)} />}
         </div>
     );
 
@@ -510,8 +505,8 @@ export class GPTPopup extends ObservableReactComponent<object> {
                 <ReactLoading type="spin" color="#bcbcbc" width={14} height={14} />
             ) : (
                 <>
-                    {(this._mode === GPTPopupMode.SORT || this._mode === GPTPopupMode.QUIZ) && (
-                        <IconButton color={StrCast(SettingsManager.userVariantColor)} tooltip="back" icon={<CgCornerUpLeft size="16px" />} onClick={() => (this._mode = GPTPopupMode.CARD)} style={{ right: '50px', position: 'absolute' }} />
+                    {(this._mode === GPTPopupMode.USER_PROMPT || this._mode === GPTPopupMode.QUIZ_RESPONSE) && (
+                        <IconButton color={StrCast(SettingsManager.userVariantColor)} tooltip="back" icon={<CgCornerUpLeft size="16px" />} onClick={() => (this._mode = GPTPopupMode.GPT_MENU)} style={{ right: '50px', position: 'absolute' }} />
                     )}
                     <Toggle
                         tooltip="Clear Chat filter"
@@ -534,13 +529,13 @@ export class GPTPopup extends ObservableReactComponent<object> {
                 {(() => {
                     //prettier-ignore
                     switch (this._mode) {
-                        case GPTPopupMode.SORT:
-                        case GPTPopupMode.CARD:
-                        case GPTPopupMode.QUIZ:    return this.sortBox(this._mode === GPTPopupMode.SORT);
-                        case GPTPopupMode.SUMMARY: return this.summaryBox();
-                        case GPTPopupMode.DATA:    return this.dataAnalysisBox();
-                        case GPTPopupMode.IMAGE:   return this.imageBox();
-                        default:                   return null;
+                        case GPTPopupMode.GPT_MENU:
+                        case GPTPopupMode.USER_PROMPT:
+                        case GPTPopupMode.QUIZ_RESPONSE: return this.promptBox(this._mode === GPTPopupMode.USER_PROMPT);
+                        case GPTPopupMode.SUMMARY:       return this.summaryBox();
+                        case GPTPopupMode.DATA:          return this.dataAnalysisBox();
+                        case GPTPopupMode.IMAGE:         return this.imageBox();
+                        default:                         return null;
                 }
                 })()}
                 <div className="resize-handle" />
-- 
cgit v1.2.3-70-g09d2

