aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/pdf
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/pdf')
-rw-r--r--src/client/views/pdf/GPTPopup/GPTPopup.scss69
-rw-r--r--src/client/views/pdf/GPTPopup/GPTPopup.tsx62
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>
);
}