diff options
Diffstat (limited to 'src/client/views/pdf')
| -rw-r--r-- | src/client/views/pdf/GPTPopup/GPTPopup.scss | 69 | ||||
| -rw-r--r-- | src/client/views/pdf/GPTPopup/GPTPopup.tsx | 62 |
2 files changed, 66 insertions, 65 deletions
diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.scss b/src/client/views/pdf/GPTPopup/GPTPopup.scss index 9cf318dc0..0b832f64c 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.scss +++ b/src/client/views/pdf/GPTPopup/GPTPopup.scss @@ -4,19 +4,23 @@ $greyborder: #d3d3d3; $lightgrey: #ececec; $button: #5b97ff; $highlightedText: #82e0ff; +$inputHeight: 60px; +$headingHeight: 32px; .gptPopup-summary-box { position: fixed; top: 115px; left: 75px; - width: 250px; - height: 200px; - min-height: 200px; - min-width: 180px; - + width: 100%; + height: 100%; + top: 0; + left: 0; + pointer-events: none; + border-top: solid gray 20px; border-radius: 16px; padding: 16px; padding-bottom: 0; + padding-top: 0px; z-index: 999; display: flex; flex-direction: column; @@ -24,17 +28,12 @@ $highlightedText: #82e0ff; background-color: #ffffff; box-shadow: 0 2px 5px #7474748d; color: $textgrey; - resize: both; /* Allows resizing */ - overflow: auto; - - .resize-handle { - width: 10px; - height: 10px; - background: #ccc; - position: absolute; - right: 0; - bottom: 0; - cursor: se-resize; + + .gptPopup-sortBox { + display: flex; + flex-direction: column; + height: calc(100% - $inputHeight - $headingHeight); + pointer-events: all; } .summary-heading { @@ -42,7 +41,7 @@ $highlightedText: #82e0ff; justify-content: space-between; align-items: center; border-bottom: 1px solid $greyborder; - padding-bottom: 5px; + height: $headingHeight; .summary-text { font-size: 12px; @@ -66,28 +65,17 @@ $highlightedText: #82e0ff; .gptPopup-content-wrapper { padding-top: 10px; min-height: 50px; - // max-height: 150px; - overflow-y: auto; - height: 100%; + height: calc(100% - 32px); } - .btns-wrapper-gpt { - height: 100%; + .inputWrapper { display: flex; justify-content: center; align-items: center; - flex-direction: column; - - .inputWrapper { - display: flex; - justify-content: center; - align-items: center; - height: 60px; - position: absolute; - bottom: 0; - width: 100%; - background-color: white; - } + height: $inputHeight; + background-color: white; + width: 100%; + pointer-events: all; .searchBox-input { height: 40px; @@ -97,14 +85,21 @@ $highlightedText: #82e0ff; border-color: #5b97ff; width: 90%; } + } + .btns-wrapper-gpt { + height: 100%; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; .chat-wrapper { display: flex; flex-direction: column; width: 100%; - max-height: calc(100vh - 80px); + height: 100%; overflow-y: auto; - padding-bottom: 60px; + padding-right: 5px; } .chat-bubbles { @@ -194,7 +189,7 @@ $highlightedText: #82e0ff; .image-content-wrapper { display: flex; flex-direction: column; - align-items: flex-start; + align-items: center; gap: 8px; padding-bottom: 16px; diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx index f09d786d0..72381cfad 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx +++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx @@ -3,7 +3,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { CgClose, CgCornerUpLeft } from 'react-icons/cg'; +import { CgCornerUpLeft } from 'react-icons/cg'; import ReactLoading from 'react-loading'; import { TypeAnimation } from 'react-type-animation'; import { ClientUtils } from '../../../../ClientUtils'; @@ -108,8 +108,6 @@ export class GPTPopup extends ObservableReactComponent<object> { @observable private _mode: GPTPopupMode = GPTPopupMode.SUMMARY; @action public setMode = (mode: GPTPopupMode) => (this._mode = mode); - @observable public Visible: boolean = false; - @action public setVisible = (vis: boolean) => (this.Visible = vis); onQuizRandom?: () => void; onGptResponse?: (sortResult: string, questionType: GPTTypeStyle, tag?: string) => void; @@ -233,10 +231,10 @@ export class GPTPopup extends ObservableReactComponent<object> { */ generateImage = (imgDesc: string, imgTarget: Doc, addToCollection?: (doc: Doc | Doc[], annotationKey?: string | undefined) => boolean) => { this._imgTargetDoc = imgTarget; + SnappingManager.SetChatVisible(true); this.addDoc = addToCollection; this.setImgUrls([]); this.setMode(GPTPopupMode.IMAGE); - this.setVisible(true); this.setGptProcessing(true); this._imageDescription = imgDesc; @@ -259,8 +257,8 @@ export class GPTPopup extends ObservableReactComponent<object> { * @param text the text to summarizz */ generateSummary = (text: string) => { + SnappingManager.SetChatVisible(true); this._textToSummarize = text; - this.setVisible(true); this.setMode(GPTPopupMode.SUMMARY); this.setGptProcessing(true); return gptAPICall(text, GPTCallType.SUMMARY) @@ -274,7 +272,6 @@ export class GPTPopup extends ObservableReactComponent<object> { * this.dataJson in the popup. */ generateDataAnalysis = () => { - this.setVisible(true); this.setGptProcessing(true); return gptAPICall(this._dataJson, GPTCallType.DATA, this._dataChatPrompt) .then(res => { @@ -398,7 +395,7 @@ export class GPTPopup extends ObservableReactComponent<object> { } }; - gptUserInput = (isUserPrompt: boolean) => ( + gptUserInput = () => ( <div className="btns-wrapper-gpt"> <div className="chat-wrapper"> <div className="chat-bubbles"> @@ -412,6 +409,15 @@ export class GPTPopup extends ObservableReactComponent<object> { <div ref={this._messagesEndRef} style={{ height: '100px' }} /> </div> + </div> + ); + + promptBox = (isUserPrompt: boolean) => ( + <> + <div className="gptPopup-sortBox"> + {this.heading(isUserPrompt ? 'ASK' : 'QUIZ')} + {this.gptUserInput()} + </div> <div className="inputWrapper"> <input className="searchBox-input" @@ -423,29 +429,31 @@ export class GPTPopup extends ObservableReactComponent<object> { placeholder={`${isUserPrompt ? 'Have ChatGPT sort, tag, define, or filter your documents for you!' : 'Describe/answer the selected document!'}`} /> </div> - </div> + </> ); - promptBox = (isUserPrompt: boolean) => ( - <div className="gptPopup-sortBox" style={{ height: '80%' }}> - {this.heading(isUserPrompt ? 'SORTING' : 'QUIZ')} - {this._mode === GPTPopupMode.GPT_MENU ? this.gptMenu() : this.gptUserInput(isUserPrompt)} + menuBox = () => ( + <div className="gptPopup-sortBox"> + {this.heading('CHOOSE')} + {this.gptMenu()} </div> ); imageBox = () => ( - <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}> + <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem', overflow: 'auto', height: '100%', pointerEvents: 'all' }}> {this.heading('GENERATED IMAGE')} <div className="image-content-wrapper"> {this._imgUrls.map((rawSrc, i) => ( - <div key={rawSrc[0] + i} className="img-wrapper"> - <div className="img-container"> - <img key={rawSrc[0]} src={rawSrc[0]} width={150} height={150} alt="dalle generation" /> + <> + <div key={rawSrc[0] + i} className="img-wrapper"> + <div className="img-container"> + <img key={rawSrc[0]} src={rawSrc[0]} width={150} height={150} alt="dalle generation" /> + </div> </div> <div className="btn-container"> <Button text="Save Image" onClick={() => this.transferToImage(rawSrc[1])} color={StrCast(Doc.UserDoc().userColor)} type={Type.TERT} /> </div> - </div> + </> ))} </div> {this._gptProcessing ? null : ( @@ -461,7 +469,7 @@ export class GPTPopup extends ObservableReactComponent<object> { summaryBox = () => ( <> - <div> + <div style={{ height: 'calc(100% - 60px)', overflow: 'auto' }}> {this.heading('SUMMARY')} <div className="gptPopup-content-wrapper"> {!this._gptProcessing && @@ -481,7 +489,7 @@ export class GPTPopup extends ObservableReactComponent<object> { </div> </div> {!this._gptProcessing && ( - <div className="btns-wrapper"> + <div className="btns-wrapper" style={{ position: 'absolute', bottom: 0, width: 'calc(100% - 32px)' }}> {this._stopAnimatingResponse ? ( <> <IconButton tooltip="Generate Again" onClick={() => this.generateSummary(this._textToSummarize + ' ')} icon={<FontAwesomeIcon icon="redo-alt" size="lg" />} color={StrCast(SettingsManager.userVariantColor)} /> @@ -571,19 +579,18 @@ export class GPTPopup extends ObservableReactComponent<object> { <ReactLoading type="spin" color="#bcbcbc" width={14} height={14} /> ) : ( <> - {(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" toggleType={ToggleType.BUTTON} type={Type.PRIM} toggleStatus={Doc.hasDocFilter(this._collectionContext, 'tags', '#chat')} text={Doc.hasDocFilter(this._collectionContext, 'tags', '#chat') ? 'filtered' : ''} - color="red" + color={Doc.hasDocFilter(this._collectionContext, 'tags', '#chat') ? 'red' : 'transparent'} onClick={() => this._collectionContext && Doc.setDocFilter(this._collectionContext, 'tags', '#chat', 'remove')} /> - <IconButton color={StrCast(SettingsManager.userVariantColor)} tooltip="close" icon={<CgClose size="16px" />} onClick={() => this.setVisible(false)} /> + {(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)} /> + )} </> )} </div> @@ -591,20 +598,19 @@ export class GPTPopup extends ObservableReactComponent<object> { render() { return ( - <div className="gptPopup-summary-box" style={{ display: this.Visible ? 'flex' : 'none' }}> + <div className="gptPopup-summary-box" style={{ display: SnappingManager.ChatVisible ? 'flex' : 'none', overflow: 'auto' }}> {(() => { //prettier-ignore switch (this._mode) { - case GPTPopupMode.GPT_MENU: - case GPTPopupMode.USER_PROMPT: + case GPTPopupMode.USER_PROMPT: case GPTPopupMode.QUIZ_RESPONSE: return this.promptBox(this._mode === GPTPopupMode.USER_PROMPT); + case GPTPopupMode.GPT_MENU: return this.menuBox(); 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" /> </div> ); } |
