aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/pdf
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2024-04-24 19:09:38 -0400
committerbobzel <zzzman@gmail.com>2024-04-24 19:09:38 -0400
commitb9825ff743ea853139a4072ce871d36d00227c4b (patch)
tree01ba5f2a9341bd183284dddc06c06333bdae59fe /src/client/views/pdf
parentb1376d401e709515cee078cc08b05fd3fb89caeb (diff)
parentbb5a5f086fc3d93051106f12398f3889d570d225 (diff)
mereged sarah-dataViz-ai
Diffstat (limited to 'src/client/views/pdf')
-rw-r--r--src/client/views/pdf/AnchorMenu.tsx17
-rw-r--r--src/client/views/pdf/GPTPopup/GPTPopup.tsx159
2 files changed, 133 insertions, 43 deletions
diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx
index 7b959533f..f02c56471 100644
--- a/src/client/views/pdf/AnchorMenu.tsx
+++ b/src/client/views/pdf/AnchorMenu.tsx
@@ -7,14 +7,13 @@ import { ColorResult } from 'react-color';
import { ClientUtils, returnFalse, setupMoveUpEvents } from '../../../ClientUtils';
import { emptyFunction, unimplementedFunction } from '../../../Utils';
import { Doc, Opt } from '../../../fields/Doc';
-import { GPTCallType, gptAPICall } from '../../apis/gpt/GPT';
import { DocumentType } from '../../documents/DocumentTypes';
import { SelectionManager } from '../../util/SelectionManager';
import { SettingsManager } from '../../util/SettingsManager';
import { AntimodeMenu, AntimodeMenuProps } from '../AntimodeMenu';
import { LinkPopup } from '../linking/LinkPopup';
import './AnchorMenu.scss';
-import { GPTPopup, GPTPopupMode } from './GPTPopup/GPTPopup';
+import { GPTPopup } from './GPTPopup/GPTPopup';
@observer
export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
@@ -77,18 +76,8 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
* @param e pointer down event
*/
gptSummarize = async () => {
- // move this logic to gptpopup, need to implement generate again
- GPTPopup.Instance.setVisible(true);
- GPTPopup.Instance.setMode(GPTPopupMode.SUMMARY);
- GPTPopup.Instance.setLoading(true);
-
- try {
- const res = await gptAPICall(this.selectedText, GPTCallType.SUMMARY);
- GPTPopup.Instance.setText(res || 'Something went wrong.');
- } catch (err) {
- console.error(err);
- }
- GPTPopup.Instance.setLoading(false);
+ GPTPopup.Instance?.setSelectedText(this.selectedText);
+ GPTPopup.Instance.generateSummary();
};
pointerDown = (e: React.PointerEvent) => {
diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
index 4362c4fbb..560f2fd27 100644
--- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx
+++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
@@ -11,7 +11,7 @@ import { ClientUtils } from '../../../../ClientUtils';
import { Doc } from '../../../../fields/Doc';
import { NumCast, StrCast } from '../../../../fields/Types';
import { Networking } from '../../../Network';
-import { gptImageCall } from '../../../apis/gpt/GPT';
+import { GPTCallType, gptAPICall, gptImageCall } from '../../../apis/gpt/GPT';
import { DocUtils, Docs } from '../../../documents/Documents';
import { ObservableReactComponent } from '../../ObservableReactComponent';
import { AnchorMenu } from '../AnchorMenu';
@@ -21,6 +21,7 @@ export enum GPTPopupMode {
SUMMARY,
EDIT,
IMAGE,
+ DATA,
}
interface GPTPopupProps {}
@@ -29,6 +30,7 @@ interface GPTPopupProps {}
export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
// eslint-disable-next-line no-use-before-define
static Instance: GPTPopup;
+ @observable private chatMode: boolean = false;
@observable
public visible: boolean = false;
@@ -48,6 +50,20 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
public setText = (text: string) => {
this.text = text;
};
+ @observable
+ public selectedText: string = '';
+ @action
+ public setSelectedText = (text: string) => {
+ this.selectedText = text;
+ };
+ @observable
+ public dataJson: string = '';
+ public dataChatPrompt: string | null = null;
+ @action
+ public setDataJson = (text: string) => {
+ if (text == '') this.dataChatPrompt = '';
+ this.dataJson = text;
+ };
@observable
public imgDesc: string = '';
@@ -79,6 +95,7 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
@action
public setDone = (done: boolean) => {
this.done = done;
+ this.chatMode = false;
};
// change what can be a ref into a ref
@@ -117,20 +134,48 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
this.setLoading(true);
try {
- const imageUrls = await gptImageCall(this.imgDesc);
- if (imageUrls && imageUrls[0]) {
- const [result] = await Networking.PostToServer('/uploadRemoteImage', { sources: [imageUrls[0]] });
+ const image_urls = await gptImageCall(this.imgDesc);
+ console.log('Image urls: ', image_urls);
+ if (image_urls && image_urls[0]) {
+ const [result] = await Networking.PostToServer('/uploadRemoteImage', { sources: [image_urls[0]] });
+ console.log('Upload result: ', result);
const source = ClientUtils.prepend(result.accessPaths.agnostic.client);
- this.setImgUrls([[imageUrls[0], source]]);
+ console.log('Upload source: ', source);
+ this.setImgUrls([[image_urls[0], source]]);
}
} catch (err) {
- console.log(err);
- return '';
+ console.error(err);
}
this.setLoading(false);
return undefined;
};
+ generateSummary = async () => {
+ GPTPopup.Instance.setVisible(true);
+ GPTPopup.Instance.setMode(GPTPopupMode.SUMMARY);
+ GPTPopup.Instance.setLoading(true);
+
+ try {
+ const res = await gptAPICall(this.selectedText, GPTCallType.SUMMARY);
+ GPTPopup.Instance.setText(res || 'Something went wrong.');
+ } catch (err) {
+ console.error(err);
+ }
+ GPTPopup.Instance.setLoading(false);
+ };
+
+ generateDataAnalysis = async () => {
+ GPTPopup.Instance.setVisible(true);
+ GPTPopup.Instance.setLoading(true);
+ try {
+ let res = await gptAPICall(this.dataJson, GPTCallType.DATA, this.dataChatPrompt);
+ GPTPopup.Instance.setText(res || 'Something went wrong.');
+ } catch (err) {
+ console.error(err);
+ }
+ GPTPopup.Instance.setLoading(false);
+ };
+
/**
* Transfers the summarization text to a sidebar annotation text document.
*/
@@ -175,6 +220,16 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
DocUtils.MakeLink(textAnchor, newDoc, { link_relationship: 'Image Prompt' });
};
+ /**
+ * Creates a chatbox for analyzing data so that users can ask specific questions.
+ */
+ private chatWithAI = () => {
+ this.chatMode = true;
+ };
+ dataPromptChanged = action((e: React.ChangeEvent<HTMLInputElement>) => {
+ this.dataChatPrompt = e.target.value;
+ });
+
private getPreviewUrl = (source: string) => source.split('.').join('_m.');
constructor(props: GPTPopupProps) {
@@ -208,25 +263,6 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
</div>
);
- data = () => (
- <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
- {this.heading('GENERATED IMAGE')}
- <div className="image-content-wrapper">
- {this.imgUrls.map(rawSrc => (
- <div className="img-wrapper">
- <div className="img-container">
- <img key={rawSrc[0]} src={rawSrc[0]} width={150} height={150} alt="dalle generation" />
- </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.loading && <IconButton tooltip="Generate Again" onClick={this.generateImage} icon={<FontAwesomeIcon icon="redo-alt" size="lg" />} color={StrCast(Doc.UserDoc().userVariantColor)} />}
- </div>
- );
-
summaryBox = () => (
<>
<div>
@@ -244,7 +280,6 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
}, 500);
},
]}
- // cursor={{ hideWhenDone: true }}
/>
) : (
this.text
@@ -255,7 +290,7 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
<div className="btns-wrapper">
{this.done ? (
<>
- <IconButton tooltip="Generate Again" onClick={this.callSummaryApi} icon={<FontAwesomeIcon icon="redo-alt" size="lg" />} color={StrCast(Doc.UserDoc().userVariantColor)} />
+ <IconButton tooltip="Generate Again" onClick={this.generateSummary} icon={<FontAwesomeIcon icon="redo-alt" size="lg" />} color={StrCast(Doc.UserDoc().userVariantColor)} />
<Button tooltip="Transfer to text" text="Transfer To Text" onClick={this.transferToText} color={StrCast(Doc.UserDoc().userVariantColor)} type={Type.TERT} />
</>
) : (
@@ -277,6 +312,72 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
</>
);
+ dataAnalysisBox = () => (
+ <>
+ <div>
+ {this.heading('ANALYSIS')}
+ <div className="content-wrapper">
+ {!this.loading &&
+ (!this.done ? (
+ <TypeAnimation
+ speed={50}
+ sequence={[
+ this.text,
+ () => {
+ setTimeout(() => {
+ this.setDone(true);
+ }, 500);
+ },
+ ]}
+ />
+ ) : (
+ this.text
+ ))}
+ </div>
+ </div>
+ {!this.loading && (
+ <div className="btns-wrapper">
+ {this.done ? (
+ this.chatMode ? (
+ <input
+ defaultValue=""
+ autoComplete="off"
+ onChange={this.dataPromptChanged}
+ onKeyDown={e => {
+ e.key === 'Enter' ? this.generateDataAnalysis() : null;
+ e.stopPropagation();
+ }}
+ type="text"
+ placeholder="Ask GPT a question about the data..."
+ id="search-input"
+ className="searchBox-input"
+ style={{ width: '100%' }}
+ />
+ ) : (
+ <>
+ <Button tooltip="Transfer to text" text="Transfer To Text" onClick={this.transferToText} color={StrCast(Doc.UserDoc().userVariantColor)} type={Type.TERT} />
+ <Button tooltip="Chat with AI" text="Chat with AI" onClick={this.chatWithAI} color={StrCast(Doc.UserDoc().userVariantColor)} type={Type.TERT} />
+ </>
+ )
+ ) : (
+ <div className="summarizing">
+ <span>Summarizing</span>
+ <ReactLoading type="bubbles" color="#bcbcbc" width={20} height={20} />
+ <Button
+ text="Stop Animation"
+ onClick={() => {
+ this.setDone(true);
+ }}
+ color={StrCast(Doc.UserDoc().userVariantColor)}
+ type={Type.TERT}
+ />
+ </div>
+ )}
+ </div>
+ )}
+ </>
+ );
+
aiWarning = () =>
this.done ? (
<div className="ai-warning">
@@ -295,7 +396,7 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
render() {
return (
<div className="summary-box" style={{ display: this.visible ? 'flex' : 'none' }}>
- {this.mode === GPTPopupMode.SUMMARY ? this.summaryBox() : this.mode === GPTPopupMode.IMAGE ? this.imageBox() : null}
+ {this.mode === GPTPopupMode.SUMMARY ? this.summaryBox() : this.mode === GPTPopupMode.DATA ? this.dataAnalysisBox() : this.mode === GPTPopupMode.IMAGE ? this.imageBox() : <></>}
</div>
);
}