From e95d25eb8159bb7c753fa27e74e9baa8d3bffea6 Mon Sep 17 00:00:00 2001
From: alyssaf16 <alyssa_feinberg@brown.edu>
Date: Sat, 30 Mar 2024 00:06:27 -0400
Subject: working on making flashcards from pdf with ai

---
 src/client/views/nodes/ComparisonBox.tsx | 181 +++++++++++++++++++++++--------
 1 file changed, 138 insertions(+), 43 deletions(-)

(limited to 'src/client/views/nodes/ComparisonBox.tsx')

diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx
index 81f624b20..ce862cd22 100644
--- a/src/client/views/nodes/ComparisonBox.tsx
+++ b/src/client/views/nodes/ComparisonBox.tsx
@@ -4,13 +4,14 @@ import { observer } from 'mobx-react';
 import * as React from 'react';
 import { emptyFunction, returnFalse, returnNone, returnZero, setupMoveUpEvents } from '../../../Utils';
 import { Doc, Opt } from '../../../fields/Doc';
-import { DocCast, NumCast, StrCast } from '../../../fields/Types';
+import { DocCast, NumCast, RTFCast, StrCast } from '../../../fields/Types';
 import { DocUtils, Docs } from '../../documents/Documents';
 import { DragManager, dropActionType } from '../../util/DragManager';
 import { undoBatch } from '../../util/UndoManager';
 import { SnappingManager } from '../../util/SnappingManager';
 import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent';
 import { StyleProp } from '../StyleProvider';
+import { Tooltip } from '@mui/material';
 import { CSSTransition } from 'react-transition-group';
 import './ComparisonBox.scss';
 import { DocumentView } from './DocumentView';
@@ -18,6 +19,8 @@ import { FieldView, FieldViewProps } from './FieldView';
 import { PinProps, PresBox } from './trails';
 import { FormattedTextBox } from './formattedText/FormattedTextBox';
 import { RichTextField } from '../../../fields/RichTextField';
+import { GPTCallType, gptAPICall } from '../../apis/gpt/GPT';
+import { DocData } from '../../../fields/DocSymbols';
 
 @observer
 export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implements ViewBoxInterface {
@@ -88,7 +91,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
                     if (this._isAnyChildContentActive) return;
                     this._animating = 'all 200ms';
                     // on click, animate slider movement to the targetWidth
-                    this.layoutDoc[this.clipWidthKey] = (targetWidth * 100) / this._props.PanelWidth();
+                    // this.layoutDoc[this.clipWidthKey] = (targetWidth * 100) / this._props.PanelWidth();
+                    this.layoutDoc[this.clipHeightKey] = (targetWidth * 100) / this._props.PanelHeight();
 
                     setTimeout(
                         action(() => (this._animating = '')),
@@ -128,7 +132,6 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
     clearDoc = (fieldKey: string) => {
         delete this.dataDoc[fieldKey];
         this.dataDoc[fieldKey] = 'empty';
-        // this.dataDoc[this.fieldKey + '_1'] = 'empty';
     };
     // clearDoc = (fieldKey: string) => delete this.dataDoc[fieldKey];
 
@@ -182,47 +185,72 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
 
         this.layoutDoc[`_${this._props.fieldKey}_usePath`] = usePath === undefined ? 'alternate' : undefined;
     };
+    hoverFlip = (side: string | undefined) => {
+        if (this.layoutDoc[`_${this._props.fieldKey}_revealOp`] == 'hover') this.layoutDoc[`_${this._props.fieldKey}_usePath`] = side;
+    };
 
     @computed get overlayAlternateIcon() {
         const usepath = this.layoutDoc[`_${this._props.fieldKey}_usePath`];
         return (
-            <div
-                className="formattedTextBox-alternateButton"
-                onPointerDown={e =>
-                    setupMoveUpEvents(e.target, e, returnFalse, emptyFunction, e => {
-                        console.log(this.layoutDoc[`_${this._props.fieldKey}_revealOp`]);
-                        if (!this.layoutDoc[`_${this._props.fieldKey}_revealOp`] || this.layoutDoc[`_${this._props.fieldKey}_revealOp`] == 'flip') {
-                            this.flipFlashcard();
-                        }
-                    })
-                }
-                style={{
-                    //display: this._props.isContentActive() && !SnappingManager.IsDragging ? 'flex' : 'none',
-                    background: usepath === 'alternate' ? 'white' : 'black',
-                    color: usepath === 'alternate' ? 'black' : 'white',
-                }}>
-                <FontAwesomeIcon icon="turn-up" size="sm" />
-            </div>
+            <Tooltip title={<div className="dash-tooltip">flip</div>}>
+                <div
+                    className="formattedTextBox-alternateButton"
+                    onPointerDown={e =>
+                        setupMoveUpEvents(e.target, e, returnFalse, emptyFunction, e => {
+                            console.log(this.layoutDoc[`_${this._props.fieldKey}_revealOp`]);
+                            if (!this.layoutDoc[`_${this._props.fieldKey}_revealOp`] || this.layoutDoc[`_${this._props.fieldKey}_revealOp`] == 'flip') {
+                                this.flipFlashcard();
+                            }
+                        })
+                    }
+                    style={{
+                        //display: this._props.isContentActive() && !SnappingManager.IsDragging ? 'flex' : 'none',
+                        background: usepath === 'alternate' ? 'white' : 'black',
+                        color: usepath === 'alternate' ? 'black' : 'white',
+                    }}>
+                    <FontAwesomeIcon icon="turn-up" size="sm" />
+                </div>
+            </Tooltip>
         );
     }
 
     render() {
         const clearButton = (which: string) => {
             return (
-                <div
-                    ref={this._closeRef}
-                    className={`clear-button ${which}`}
-                    onPointerDown={e => this.closeDown(e, which)} // prevent triggering slider movement in registerSliding
-                >
-                    <FontAwesomeIcon className={`clear-button ${which}`} icon="times" size="sm" />
-                </div>
+                <Tooltip title={<div className="dash-tooltip">remove</div>}>
+                    <div
+                        ref={this._closeRef}
+                        className={`clear-button ${which}`}
+                        onPointerDown={e => this.closeDown(e, which)} // prevent triggering slider movement in registerSliding
+                    >
+                        <FontAwesomeIcon className={`clear-button ${which}`} icon="times" size="sm" />
+                    </div>
+                </Tooltip>
             );
         };
         const displayDoc = (which: string) => {
             const whichDoc = DocCast(this.dataDoc[which]);
             const targetDoc = DocCast(whichDoc?.annotationOn, whichDoc);
             // if there is no Doc in the first comparison slot, but the comparison box's fieldKey slot has a RichTextField, then render a text box to show the contents of the document's field key slot
-            const layoutTemplateString = !targetDoc && which.endsWith('1') && this.Document[this.fieldKey] instanceof RichTextField ? FormattedTextBox.LayoutString(this.fieldKey) : undefined;
+            //const layoutTemplateString = !targetDoc && which.endsWith('1') && this.Document[this.fieldKey] instanceof RichTextField ? FormattedTextBox.LayoutString(this.fieldKey) : undefined;
+            const subjectText = RTFCast(this.Document[this.fieldKey])?.Text;
+            const layoutTemplateString = !targetDoc
+                ? which.endsWith('0') && subjectText !== undefined
+                    ? FormattedTextBox.LayoutString(this.fieldKey)
+                    : which.endsWith('1') && (this.Document[which] instanceof RichTextField || typeof this.Document[which] === 'string')
+                      ? FormattedTextBox.LayoutString(which)
+                      : undefined
+                : undefined;
+
+            if (which.endsWith('1') && !layoutTemplateString && targetDoc) {
+                const queryText = RTFCast(this.Document[this.fieldKey + '_1'])?.Text;
+                console.log('QUER' + queryText);
+                if (queryText?.includes('--TEXT--') && subjectText) {
+                    this.Document[DocData][this.fieldKey + '_1'] = '';
+                    gptAPICall(queryText?.replace('--TEXT--', subjectText), GPTCallType.COMPLETION).then(value => (this.Document[DocData][this.fieldKey + '_1'] = value.trim()));
+                }
+            }
+
             return targetDoc || layoutTemplateString ? (
                 <>
                     <DocumentView
@@ -234,7 +262,9 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
                         moveDocument={which.endsWith('1') ? this.moveDoc1 : this.moveDoc2}
                         removeDocument={which.endsWith('1') ? this.remDoc1 : this.remDoc2}
                         NativeWidth={() => NumCast(this.layoutDoc.width, 200)}
-                        NativeHeight={() => NumCast(this.layoutDoc.height, 200)}
+                        NativeHeight={(): number => {
+                            return NumCast(this.layoutDoc.height, 200);
+                        }}
                         isContentActive={emptyFunction}
                         isDocumentActive={returnFalse}
                         whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
@@ -251,6 +281,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
             );
         };
         const displayBox = (which: string, index: number, cover: number) => {
+            // if (this.layoutDoc[`_${this._props.fieldKey}_revealOp`] == 'hide/reveal') this.layoutDoc[this.clipHeightKey] = 100;
+            // else this.layoutDoc.height = 300;
             return (
                 <div className={`${index === 0 ? 'before' : 'after'}Box-cont`} key={which} style={{ width: this._props.PanelWidth() }} onPointerDown={e => this.registerSliding(e, cover)} ref={ele => this.createDropTarget(ele, which, index)}>
                     {displayDoc(which)}
@@ -258,26 +290,89 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
             );
         };
 
+        const displayBoxReveal = (which: string, which2: string, index: number, cover: number) => {
+            return (
+                <div style={{ display: 'flex', flexDirection: 'column' }}>
+                    <div
+                        className={`beforeBox-cont`}
+                        key={which}
+                        style={{ width: this._props.PanelWidth(), height: NumCast(this.layoutDoc.height, 200) / 2 }}
+                        onPointerDown={e => this.registerSliding(e, cover)}
+                        ref={ele => this.createDropTarget(ele, which, 0)}>
+                        {displayDoc(which)}
+                    </div>
+                    <div
+                        className={`afterBox-cont`}
+                        key={which2}
+                        style={{ width: this._props.PanelWidth(), height: NumCast(this.layoutDoc.height, 200) / 2 }}
+                        onPointerDown={e => this.registerSliding(e, cover)}
+                        ref={ele => this.createDropTarget(ele, which2, 1)}>
+                        {displayDoc(which2)}
+                    </div>
+                </div>
+            );
+        };
+
         if (this.Document._layout_isFlashcard) {
             const side = this.layoutDoc[`_${this._props.fieldKey}_usePath`] === 'alternate' ? 1 : 0;
 
-            if (!(this.dataDoc[this.fieldKey + '_0'] || this.dataDoc[this.fieldKey + '_0'] == 'empty')) this.dataDoc[this.fieldKey + '_0'] = DocUtils.copyDragFactory(Doc.UserDoc().emptyNote as Doc);
+            // add text box when first created
+            if (!(this.dataDoc[this.fieldKey + '_0'] || this.dataDoc[this.fieldKey + '_0'] == 'empty')) {
+                console.log('TEXT HERE' + this.dataDoc.data);
+                const newDoc = Docs.Create.TextDocument(StrCast(this.dataDoc.data));
+                this.addDoc(newDoc, this.fieldKey + '_0');
+            }
+            // if (!(this.dataDoc[this.fieldKey + '_0'] || this.dataDoc[this.fieldKey + '_0'] == 'empty')) this.dataDoc[this.fieldKey + '_0'] = DocUtils.copyDragFactory(Doc.UserDoc().emptyNote as Doc);
             if (!(this.dataDoc[this.fieldKey + '_1'] || this.dataDoc[this.fieldKey + '_1'] == 'empty')) this.dataDoc[this.fieldKey + '_1'] = DocUtils.copyDragFactory(Doc.UserDoc().emptyNote as Doc);
 
-            return (
-                <div
-                    className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}`} /* change className to easily disable/enable pointer events in CSS */
-                    onMouseEnter={() => {
-                        if (this.layoutDoc[`_${this._props.fieldKey}_revealOp`] == 'hover') this.layoutDoc[`_${this._props.fieldKey}_usePath`] = 'alternate';
-                    }}
-                    onMouseLeave={() => {
-                        if (this.layoutDoc[`_${this._props.fieldKey}_revealOp`] == 'hover') this.layoutDoc[`_${this._props.fieldKey}_usePath`] = undefined;
-                    }}>
-                    {displayBox(`${this.fieldKey}_${side}`, side, this._props.PanelWidth() - 3)}
+            if (this.layoutDoc[`_${this._props.fieldKey}_revealOp`] == 'hide/reveal') {
+                {
+                    return (
+                        <div className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}`} style={{ display: 'flex', flexDirection: 'column' }}>
+                            {displayBox(`${this.fieldKey}_0`, side, this._props.PanelHeight() - 3)}
+                            {displayBox(`${this.fieldKey}_1`, 1, this._props.PanelHeight() - 3)}
+                        </div>
+                    );
+                    // return (
+                    //     <div className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}` /* change className to easily disable/enable pointer events in CSS */} style={{ display: 'flex', flexDirection: 'column' }}>
+                    //         {displayBox(`${this.fieldKey}_2`, 1, this._props.PanelHeight() - 3)}
+                    //         <div className="clip-div" style={{ height: this.clipHeight + '%', transition: this._animating, background: StrCast(this.layoutDoc._backgroundColor, 'gray') }}>
+                    //             {displayBox(`${this.fieldKey}_1`, 0, 0)}
+                    //         </div>
+                    //     </div>
+                    // );
+                    // return (
+                    //     <div className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}` /* change className to easily disable/enable pointer events in CSS */}>
+                    //         {displayBox(`${this.fieldKey}_${side === 0 ? 1 : 0}`, side, this._props.PanelHeight() / 2)}
+                    //         {displayBox(`${this.fieldKey}_${side === 0 ? 0 : 1}`, 1, this._props.PanelHeight() / 2)}
 
-                    {this.overlayAlternateIcon}
-                </div>
-            );
+                    //     </div>
+                    // );
+                }
+            } else {
+                return (
+                    <div
+                        className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}`} /* change className to easily disable/enable pointer events in CSS */
+                        // style={{ display: 'flex', flexDirection: 'column' }}
+                        // style={{ position: 'absolute', top: '0px' }}
+                        onMouseEnter={() => {
+                            this.hoverFlip('alternate');
+                        }}
+                        onMouseLeave={() => {
+                            this.hoverFlip(undefined);
+                        }}>
+                        {displayBox(`${this.fieldKey}_${side === 0 ? 1 : 0}`, side, this._props.PanelWidth() - 3)}
+                        {/* {displayBoxReveal(`${this.fieldKey}_${side}`, side, this._props.PanelWidth() - 3)}
+                        {displayBoxReveal(`${this.fieldKey}_${side === 0 ? 1 : 0}`, side === 0 ? 1 : 0, this._props.PanelWidth() - 3)} */}
+                        {/* <div>{displayBoxReveal(`${this.fieldKey}_${side}`, side, this._props.PanelWidth() - 3)}</div> */}
+                        {/* <div style={{ display: this.layoutDoc[`_${this._props.fieldKey}_revealOp`] == 'hide/reveal' ? 'block' : 'none' }} className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}`}>
+                            {displayBox(`${this.fieldKey}_${side === 0 ? 1 : 0}`, side === 0 ? 1 : 0, this._props.PanelWidth() - 3)}
+                        </div> */}
+
+                        {this.overlayAlternateIcon}
+                    </div>
+                );
+            }
         } else {
             return (
                 <div className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}` /* change className to easily disable/enable pointer events in CSS */}>
-- 
cgit v1.2.3-70-g09d2

