From 078d595cb498592667a653a937b8ba25bcbf41bb Mon Sep 17 00:00:00 2001 From: Sophie Zhang Date: Thu, 20 Jul 2023 00:54:07 -0400 Subject: refactoring gpt functionalities --- src/client/views/MainView.tsx | 2 + .../views/nodes/formattedText/FormattedTextBox.tsx | 2 +- src/client/views/pdf/AnchorMenu.tsx | 157 ++++++--------------- src/client/views/pdf/GPTPopup/GPTPopup.scss | 12 +- src/client/views/pdf/GPTPopup/GPTPopup.tsx | 102 +++++++++---- src/client/views/pdf/PDFViewer.tsx | 5 + 6 files changed, 130 insertions(+), 150 deletions(-) (limited to 'src') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index a129c35cf..f6829a4cb 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -67,6 +67,7 @@ import { PropertiesView } from './PropertiesView'; import { DashboardStyleProvider, DefaultStyleProvider } from './StyleProvider'; import { TopBar } from './topbar/TopBar'; import GenerativeFill from './nodes/generativeFill/GenerativeFill'; +import { GPTPopup } from './pdf/GPTPopup/GPTPopup'; const _global = (window /* browser */ || global) /* node */ as any; @observer @@ -1032,6 +1033,7 @@ export class MainView extends React.Component { {this.snapLines} + {/* */} diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 20a176c58..212d24165 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -909,7 +909,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { try { diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx index 07b2afd91..e6b9cb382 100644 --- a/src/client/views/pdf/AnchorMenu.tsx +++ b/src/client/views/pdf/AnchorMenu.tsx @@ -48,9 +48,6 @@ export class AnchorMenu extends AntimodeMenu { @observable public Status: 'marquee' | 'annotation' | '' = ''; // GPT additions - @observable private GPTpopupText: string = ''; - @observable private loadingGPT: boolean = false; - @observable private showGPTPopup: boolean = false; @observable private GPTMode: GPTPopupMode = GPTPopupMode.SUMMARY; @observable private selectedText: string = ''; @observable private editorView?: EditorView; @@ -58,25 +55,11 @@ export class AnchorMenu extends AntimodeMenu { @observable private highlightRange: number[] | undefined; private selectionRange: number[] | undefined; - @action - setGPTPopupVis = (vis: boolean) => { - this.showGPTPopup = vis; - }; @action setGPTMode = (mode: GPTPopupMode) => { this.GPTMode = mode; }; - @action - setGPTPopupText = (txt: string) => { - this.GPTpopupText = txt; - }; - - @action - setLoading = (loading: boolean) => { - this.loadingGPT = loading; - }; - @action setHighlightRange(r: number[] | undefined) { this.highlightRange = r; @@ -130,19 +113,12 @@ export class AnchorMenu extends AntimodeMenu { componentDidMount() { this._disposer2 = reaction( () => this._opacity, - opacity => { - if (!opacity) { - this.setGPTPopupVis(false); - this.setGPTPopupText(''); - } - }, + opacity => {}, { fireImmediately: true } ); this._disposer = reaction( () => SelectionManager.Views().slice(), selected => { - this.setGPTPopupVis(false); - this.setGPTPopupText(''); AnchorMenu.Instance.fadeOut(true); } ); @@ -153,23 +129,22 @@ export class AnchorMenu extends AntimodeMenu { * @param e pointer down event */ gptSummarize = async (e: React.PointerEvent) => { + GPTPopup.Instance.setVisible(true); this.setHighlightRange(undefined); - this.setGPTPopupVis(true); this.setGPTMode(GPTPopupMode.SUMMARY); - this.setLoading(true); + GPTPopup.Instance.setLoading(true); try { const res = await gptAPICall(this.selectedText, GPTCallType.SUMMARY); if (res) { - this.setGPTPopupText(res); + GPTPopup.Instance.setText(res); } else { - this.setGPTPopupText('Something went wrong.'); + GPTPopup.Instance.setText('Something went wrong.'); } } catch (err) { console.error(err); } - - this.setLoading(false); + GPTPopup.Instance.setLoading(false); }; /** @@ -184,9 +159,9 @@ export class AnchorMenu extends AntimodeMenu { const fullText = state.doc.textBetween(0, this.editorView.state.doc.content.size, ' \n'); const selectedText = state.doc.textBetween(sel.from, sel.to); - this.setGPTPopupVis(true); + GPTPopup.Instance.setVisible(true); this.setGPTMode(GPTPopupMode.EDIT); - this.setLoading(true); + GPTPopup.Instance.setLoading(true); try { let res = await gptAPICall(selectedText, GPTCallType.EDIT); @@ -196,16 +171,16 @@ export class AnchorMenu extends AntimodeMenu { const resultText = fullText.slice(0, sel.from - 1) + res + fullText.slice(sel.to - 1); if (res) { - this.setGPTPopupText(resultText); + GPTPopup.Instance.setText(resultText); this.setHighlightRange([sel.from - 1, sel.from - 1 + res.length]); } else { - this.setGPTPopupText('Something went wrong.'); + GPTPopup.Instance.setText('Something went wrong.'); } } catch (err) { console.error(err); } - this.setLoading(false); + GPTPopup.Instance.setLoading(false); }; /** @@ -253,21 +228,18 @@ export class AnchorMenu extends AntimodeMenu { }; @computed get highlighter() { - return - } - tooltip={'Click to Highlight'} - onClick={this.highlightClicked} - colorPicker={this.highlightColor} - color={StrCast(Doc.UserDoc().userColor)} - /> - this.changeHighlightColor(color)} - size={Size.XSMALL} - /> - + return ( + + } + tooltip={'Click to Highlight'} + onClick={this.highlightClicked} + colorPicker={this.highlightColor} + color={StrCast(Doc.UserDoc().userColor)} + /> + this.changeHighlightColor(color)} size={Size.XSMALL} /> + + ); } @action changeHighlightColor = (color: string) => { @@ -312,12 +284,7 @@ export class AnchorMenu extends AntimodeMenu { this.Status === 'marquee' ? ( <> {this.highlighter} - } - color={StrCast(Doc.UserDoc().userColor)} - /> + } color={StrCast(Doc.UserDoc().userColor)} /> {/* GPT Summarize icon only shows up when text is highlighted, not on marquee selection*/} {AnchorMenu.Instance.StartCropDrag === unimplementedFunction && this.canSummarize() && ( Summarize with AI}> @@ -326,7 +293,7 @@ export class AnchorMenu extends AntimodeMenu { )} - { callEditApi={this.gptEdit} replaceText={this.replaceText} mode={this.GPTMode} - /> + /> */} {AnchorMenu.Instance.OnAudio === unimplementedFunction ? null : ( - } - color={StrCast(Doc.UserDoc().userColor)} - /> - )} - {this.canEdit() && ( - } - color={StrCast(Doc.UserDoc().userColor)} - /> + } color={StrCast(Doc.UserDoc().userColor)} /> )} - } - popup={} - color={StrCast(Doc.UserDoc().userColor)} - /> + {this.canEdit() && } color={StrCast(Doc.UserDoc().userColor)} />} + } popup={} color={StrCast(Doc.UserDoc().userColor)} /> {AnchorMenu.Instance.StartCropDrag === unimplementedFunction ? null : ( - } - color={StrCast(Doc.UserDoc().userColor)} - /> + } color={StrCast(Doc.UserDoc().userColor)} /> )} ) : ( <> - {this.Delete !== returnFalse && } - color={StrCast(Doc.UserDoc().userColor)} - />} - {this.PinToPres !== returnFalse && } - color={StrCast(Doc.UserDoc().userColor)} - />} - {this.ShowTargetTrail !== returnFalse && } - color={StrCast(Doc.UserDoc().userColor)} - />} - {this.IsTargetToggler !== returnFalse && } - color={StrCast(Doc.UserDoc().userColor)} - />} + {this.Delete !== returnFalse && } color={StrCast(Doc.UserDoc().userColor)} />} + {this.PinToPres !== returnFalse && } color={StrCast(Doc.UserDoc().userColor)} />} + {this.ShowTargetTrail !== returnFalse && } color={StrCast(Doc.UserDoc().userColor)} />} + {this.IsTargetToggler !== returnFalse && ( + } + color={StrCast(Doc.UserDoc().userColor)} + /> + )} ); diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.scss b/src/client/views/pdf/GPTPopup/GPTPopup.scss index 44413ede7..2f0ff83e2 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.scss +++ b/src/client/views/pdf/GPTPopup/GPTPopup.scss @@ -6,12 +6,6 @@ $button: #5b97ff; $highlightedText: #82e0ff; .summary-box { - display: flex; - flex-direction: column; - justify-content: space-between; - background-color: #ffffff; - box-shadow: 0 2px 5px #7474748d; - color: $textgrey; position: fixed; bottom: 10px; right: 10px; @@ -21,6 +15,12 @@ $highlightedText: #82e0ff; padding: 15px; padding-bottom: 0; z-index: 999; + display: flex; + flex-direction: column; + justify-content: space-between; + background-color: #ffffff; + box-shadow: 0 2px 5px #7474748d; + color: $textgrey; .summary-heading { display: flex; diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx index 8bd060d4f..9f28cb5d1 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx +++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx @@ -5,56 +5,96 @@ import { observer } from 'mobx-react'; import ReactLoading from 'react-loading'; import Typist from 'react-typist'; import { Doc } from '../../../../fields/Doc'; -import { Docs } from '../../../documents/Documents'; +import { DocUtils, Docs } from '../../../documents/Documents'; import './GPTPopup.scss'; +import { Button, IconButton } from 'browndash-components'; +import { StrCast } from '../../../../fields/Types'; export enum GPTPopupMode { SUMMARY, EDIT, } -interface GPTPopupProps { - visible: boolean; - text: string; - loading: boolean; - mode: GPTPopupMode; - callSummaryApi: (e: React.PointerEvent) => Promise; - callEditApi: (e: React.PointerEvent) => Promise; - replaceText: (replacement: string) => void; - highlightRange?: number[]; -} +interface GPTPopupProps {} @observer export class GPTPopup extends React.Component { static Instance: GPTPopup; @observable - private done: boolean = false; + public visible: boolean = false; + @action + public setVisible = (vis: boolean) => { + this.visible = vis; + }; @observable - private sidebarId: string = ''; + public loading: boolean = false; + @action + public setLoading = (loading: boolean) => { + this.loading = loading; + }; + @observable + public text: string = ''; + @action + public setText = (text: string) => { + this.text = text; + }; + @observable + public mode: GPTPopupMode = GPTPopupMode.SUMMARY; + @action + public setMode = (mode: GPTPopupMode) => { + this.mode = mode; + }; + @observable + public highlightRange: number[] = []; + @action callSummaryApi = () => {}; + @action callEditApi = () => {}; + @action replaceText = (replacement: string) => {}; + + @observable + private done: boolean = false; @action public setDone = (done: boolean) => { this.done = done; }; + @observable + private sidebarId: string = ''; @action public setSidebarId = (id: string) => { this.sidebarId = id; }; + // reference + // if (focusNode) { + // const anchor = srcWeb?.ComponentView?.getAnchor?.(true); + // anchor && DocUtils.MakeLink(htmlDoc, anchor, {}); + // } + @observable + private pdfAnchor: Doc | undefined; + @action + public setPdfAnchor = (anchor: Doc) => { + this.pdfAnchor = anchor; + }; + public addDoc: (doc: Doc | Doc[], sidebarKey?: string | undefined) => boolean = () => false; /** * Transfers the summarization text to a sidebar annotation text document. */ private transferToText = () => { - const newDoc = Docs.Create.TextDocument(this.props.text.trim(), { + const newDoc = Docs.Create.TextDocument(this.text.trim(), { _width: 200, _height: 50, _layout_fitWidth: true, _layout_autoHeight: true, }); this.addDoc(newDoc, this.sidebarId); + if (this.pdfAnchor) { + DocUtils.MakeLink(newDoc, this.pdfAnchor, { + link_relationship: 'GPT Summary', + }); + } }; constructor(props: GPTPopupProps) { @@ -63,7 +103,7 @@ export class GPTPopup extends React.Component { } componentDidUpdate = () => { - if (this.props.loading) { + if (this.loading) { this.setDone(false); } }; @@ -73,10 +113,10 @@ export class GPTPopup extends React.Component {
{this.heading('SUMMARY')}
- {!this.props.loading && + {!this.loading && (!this.done ? ( { @@ -84,18 +124,18 @@ export class GPTPopup extends React.Component { this.setDone(true); }, 500); }}> - {this.props.text} + {this.text} ) : ( - this.props.text + this.text ))}
- {!this.props.loading && ( + {!this.loading && (
{this.done ? ( <> - + */} + } color={StrCast(Doc.UserDoc().userVariantColor)} /> + @@ -174,14 +216,14 @@ export class GPTPopup extends React.Component { heading = (headingText: string) => (
- {this.props.loading && } + {this.loading && }
); render() { return ( -
- {this.props.mode === GPTPopupMode.SUMMARY ? this.summaryBox() : this.editBox()} +
+ {this.mode === GPTPopupMode.SUMMARY ? this.summaryBox() : this.editBox()}
); } diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 0fd93868a..4fc31ffe3 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -423,6 +423,11 @@ export class PDFViewer extends React.Component { // Changing which document to add the annotation to (the currently selected PDF) GPTPopup.Instance.setSidebarId('data_sidebar'); + const anchor = this._getAnchor(undefined, false); + if (anchor) { + console.log(anchor); + GPTPopup.Instance.setPdfAnchor(anchor); + } GPTPopup.Instance.addDoc = this.props.sidebarAddDoc; }; -- cgit v1.2.3-70-g09d2