diff options
| author | bobzel <zzzman@gmail.com> | 2024-04-24 19:09:38 -0400 |
|---|---|---|
| committer | bobzel <zzzman@gmail.com> | 2024-04-24 19:09:38 -0400 |
| commit | b9825ff743ea853139a4072ce871d36d00227c4b (patch) | |
| tree | 01ba5f2a9341bd183284dddc06c06333bdae59fe /src/client/views/pdf | |
| parent | b1376d401e709515cee078cc08b05fd3fb89caeb (diff) | |
| parent | bb5a5f086fc3d93051106f12398f3889d570d225 (diff) | |
mereged sarah-dataViz-ai
Diffstat (limited to 'src/client/views/pdf')
| -rw-r--r-- | src/client/views/pdf/AnchorMenu.tsx | 17 | ||||
| -rw-r--r-- | src/client/views/pdf/GPTPopup/GPTPopup.tsx | 159 |
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> ); } |
