aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/views/collections/CollectionCardDeckView.tsx52
-rw-r--r--src/client/views/pdf/GPTPopup/GPTPopup.scss33
-rw-r--r--src/client/views/pdf/GPTPopup/GPTPopup.tsx138
3 files changed, 215 insertions, 8 deletions
diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx
index e64c013f1..e96fbc161 100644
--- a/src/client/views/collections/CollectionCardDeckView.tsx
+++ b/src/client/views/collections/CollectionCardDeckView.tsx
@@ -21,7 +21,9 @@ import { List } from '../../../fields/List';
import { gptAPICall, gptImageLabel } from '../../apis/gpt/GPT';
import { GPTCallType } from '../../apis/gpt/GPT';
import { ImageField, PdfField, URLField } from '../../../fields/URLField';
-
+import { GPTPopup } from '../pdf/GPTPopup/GPTPopup';
+import { GPTPopupMode } from '../pdf/GPTPopup/GPTPopup';
+import { reaction } from 'mobx';
@observer
export class CollectionCardView extends CollectionSubView() {
@@ -88,6 +90,15 @@ export class CollectionCardView extends CollectionSubView() {
if (this._props.Document.customHashMap != undefined){
this.customGroupDictionary = this.getCustoms(StrListCast(this._props.Document.customHashMap))
}
+
+ reaction(
+ () => this._props.Document.cardSort,
+ (cardSort) => {
+ if (cardSort === 'chat') {
+ this.openChatPopup();
+ }
+ }
+ );
}
@observable customGroupDictionary: Map<number, number>[] = [new Map<number, number>(), new Map<number, number>(), new Map<number, number>()];
@@ -230,10 +241,18 @@ export class CollectionCardView extends CollectionSubView() {
@computed get sortedDocsType() {
- if (this._props.Document.cardSort === 'chat' && this.sortedDocs.length === 0) {
- this.smartSort(); // Trigger the sorting if it hasn't been done yet
- return { docs: [] }; // Return an empty array or a loading state
- }
+ // if (this._props.Document.cardSort === 'chat'){
+ // this.openChatPopup()
+ // const textDesc = await this.childPairStringList();
+ // GPTPopup.Instance.setSortDesc(textDesc)
+ // }
+
+ // if (this._props.Document.cardSort === 'chat' && this.sortedDocs.length === 0) {
+
+ // this.smartSort(); // Trigger the sorting if it hasn't been done yet
+ // return { docs: [] }; // Return an empty array or a loading state
+ // }
+
const desc = BoolCast(this.layoutDoc.sortDesc);
let sorted = [];
@@ -253,7 +272,7 @@ export class CollectionCardView extends CollectionSubView() {
case 'custom':
return this.sort(sorted, 'custom', desc);
case 'chat':
- return { docs: this.sortedDocs }; // Use the sorted docs from the observable
+ return { docs: this.sortedDocs || this.myChildLayoutPairs}; // Use the sorted docs from the observable
default:
docs = this.myChildLayoutPairs;
return { docs };
@@ -656,6 +675,25 @@ export class CollectionCardView extends CollectionSubView() {
});
}
+ @observable isChatPopupOpen = false;
+
+ @action openChatPopup = async () => {
+ this.isChatPopupOpen = true;
+ GPTPopup.Instance.setVisible(true);
+ GPTPopup.Instance.setMode(GPTPopupMode.SORT);
+
+ // Await the promise to get the string result
+ const sortDesc = await this.childPairStringList();
+ GPTPopup.Instance.setSortDesc(sortDesc);
+ GPTPopup.Instance.onSortComplete = this.handleGptSortResult;
+};
+ @action handleGptSortResult = (sortResult: string) => {
+ this.processGptOutput(sortResult);
+ this.sortedDocs = this.sort(this.myChildLayoutPairs, 'gpt', BoolCast(this.layoutDoc.sortDesc)).docs;
+ };
+
+
+
renderButtons(childPairIndex: number) {
@@ -708,6 +746,8 @@ export class CollectionCardView extends CollectionSubView() {
// }
// }
+
+
render() {
return (
<div
diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.scss b/src/client/views/pdf/GPTPopup/GPTPopup.scss
index 5d966395c..4425cf158 100644
--- a/src/client/views/pdf/GPTPopup/GPTPopup.scss
+++ b/src/client/views/pdf/GPTPopup/GPTPopup.scss
@@ -60,6 +60,17 @@ $highlightedText: #82e0ff;
display: flex;
justify-content: space-between;
align-items: center;
+ transform: translateY(30px);
+
+
+ .searchBox-input{
+ transform: translateY(-15px);
+ height: 50px;
+ border-radius: 10px;
+ border-color: #5b97ff;
+ }
+
+
.summarizing {
display: flex;
@@ -111,6 +122,28 @@ $highlightedText: #82e0ff;
}
}
+.loading-spinner {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100px;
+ font-size: 20px;
+ font-weight: bold;
+ color: #666;
+}
+
+
+
+
+
+@keyframes spin {
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+
+
.image-content-wrapper {
display: flex;
flex-direction: column;
diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
index 29b1ca365..faf66af85 100644
--- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx
+++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
@@ -21,6 +21,7 @@ export enum GPTPopupMode {
EDIT,
IMAGE,
DATA,
+ SORT
}
interface GPTPopupProps {}
@@ -94,10 +95,21 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
private done: boolean = false;
@action
public setDone = (done: boolean) => {
+ console.log("HIIIIIIIII")
this.done = done;
this.chatMode = false;
};
+ @observable
+ private sortDone: boolean = false // this is so redundant but the og done variable was causing weird unknown problems and im just a girl
+
+ @action
+ public setSortDone = (done: boolean) => {
+ console.log("HIIIIIIIII")
+ this.sortDone = done;
+ };
+
+
// change what can be a ref into a ref
@observable
private sidebarId: string = '';
@@ -120,9 +132,61 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
this.textAnchor = anchor;
};
+ @observable
+ public sortPrompt: string = '';
+ @action
+ public setSortPrompt = ((e: React.ChangeEvent<HTMLInputElement>) => {
+ this.sortPrompt = e.target.value;
+ });
+
+ @observable
+ public sortText: string = ''
+ @action
+ public setSortText = (t: string) => {
+ this.sortText = t
+ }
+
+ @observable
+ public sortDesc: string = ''
+
+ @action public setSortDesc = (t:string) => {
+ this.sortDesc = t
+ }
+
+ @observable onSortComplete?: (sortResult: string) => void;
+
+
+
+
+
+
public addDoc: (doc: Doc | Doc[], sidebarKey?: string | undefined) => boolean = () => false;
public addToCollection: ((doc: Doc | Doc[], annotationKey?: string | undefined) => boolean) | undefined;
+
+ generateSort = async () => {
+ this.setLoading(true);
+ this.setSortDone(false);
+
+ try {
+ const res = await gptAPICall(this.sortPrompt + this.sortDesc, GPTCallType.SORT);
+ this.setSortText(res || 'Something went wrong :(');
+
+ // Trigger the callback with the result
+ if (this.onSortComplete) {
+ this.onSortComplete(res || 'Something went wrong :(');
+ }
+ } catch (err) {
+ console.error(err);
+ this.setSortText('Something went wrong :(');
+ }
+
+ this.setLoading(false);
+ this.setSortDone(true);
+ }
+
+
+
/**
* Generates a Dalle image and uploads it to the server.
*/
@@ -243,6 +307,74 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
}
};
+ sortBox = () => (
+ <>
+ <div>
+ {this.heading("SORTING")}
+ {this.loading ? (
+ <div className="content-wrapper">
+ <div className="loading-spinner">
+ <ReactLoading type="spin" color="#000" height={30} width={30} />
+ <span>Loading...</span>
+ </div>
+ </div>
+ ) : !this.sortDone && (
+ <div className="btns-wrapper">
+ <input
+ defaultValue=""
+ autoComplete="off"
+ onChange={this.setSortPrompt}
+ onKeyDown={e => {
+ if (e.key === 'Enter') {
+ this.generateSort();
+ }
+ e.stopPropagation();
+ }}
+ type="text"
+ placeholder="Enter sorting instructions..."
+ id="search-input"
+ className="searchBox-input"
+ style={{ width: "100%" }}
+ />
+ </div>
+ )}
+
+ {this.sortDone && (
+ <div>
+ <div className="content-wrapper">
+
+ <p>{this.text== "Something went wrong :(" ? "Something went wrong :(" : "Sorting done! Feel free to move things around / regenerate :) !"}</p>
+
+
+ <IconButton
+ tooltip="Generate Again"
+ onClick={() => this.setSortDone(false)}
+ icon={<FontAwesomeIcon icon="redo-alt" size="lg" />}
+ color={StrCast(Doc.UserDoc().userVariantColor)}
+ />
+
+ </div>
+ </div>
+ )}
+ </div>
+ </>
+ );
+
+
+
+
+// <>
+// <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>Sorting</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>
+// )}
+
imageBox = () => {
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
@@ -396,8 +528,10 @@ 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.DATA? this.dataAnalysisBox() : this.mode === GPTPopupMode.IMAGE ? this.imageBox() : <></>}
- </div>
+ {this.mode === GPTPopupMode.SUMMARY ? this.summaryBox() :
+ this.mode === GPTPopupMode.DATA ? this.dataAnalysisBox() :
+ this.mode === GPTPopupMode.IMAGE ? this.imageBox() :
+ this.mode === GPTPopupMode.SORT ? this.sortBox() : <></>} </div>
);
}
}