diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/global/globalScripts.ts | 2 | ||||
-rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBox.tsx | 3 | ||||
-rw-r--r-- | src/client/views/pdf/GPTPopup/GPTPopup.tsx | 119 |
3 files changed, 59 insertions, 65 deletions
diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 029c4dbc7..790ebeabe 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -230,7 +230,7 @@ ScriptingGlobals.add(function showFreeform( GPTPopup.Instance.setVisible(false); } else { GPTPopup.Instance.setVisible(true); - GPTPopup.Instance.setMode(GPTPopupMode.CARD); + GPTPopup.Instance.setMode(GPTPopupMode.GPT_MENU); } }, }], diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 17b9bce47..2e14fb1d9 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1065,8 +1065,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB GPTPopup.Instance?.setTextAnchor(this.getAnchor(false)); GPTPopup.Instance?.setImgTargetDoc(this.Document); GPTPopup.Instance.addToCollection = this._props.addDocument; - GPTPopup.Instance.setImgDesc((this.dataDoc.text as RichTextField)?.Text); - GPTPopup.Instance.generateImage(); + GPTPopup.Instance.generateImage((this.dataDoc.text as RichTextField)?.Text); }; breakupDictation = () => { 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" /> |