diff options
Diffstat (limited to 'src/client/views/nodes/ComparisonBox.tsx')
-rw-r--r-- | src/client/views/nodes/ComparisonBox.tsx | 109 |
1 files changed, 76 insertions, 33 deletions
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index 19fccce8a..9fd4d696a 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -2,7 +2,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { emptyFunction, returnFalse, returnNone, returnZero, setupMoveUpEvents } from '../../../Utils'; +import { emptyFunction, returnFalse, returnNone, returnZero, setupMoveUpEvents, unimplementedFunction } from '../../../Utils'; import { Doc, Opt, DocListCast } from '../../../fields/Doc'; import { DocCast, NumCast, RTFCast, StrCast } from '../../../fields/Types'; import { DocUtils, Docs } from '../../documents/Documents'; @@ -34,6 +34,17 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() makeObservable(this); } + @observable inputValue = ''; + @observable outputValue = ''; + @observable loading = false; + @observable errorMessage = ''; + @observable outputMessage = ''; + + @action handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { + this.inputValue = e.target.value; + console.log(this.inputValue); + }; + @observable _animating = ''; @computed get clipWidth() { @@ -160,7 +171,6 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() e => { const de = new DragManager.DocumentDragData([DocCast(this.dataDoc[which])], dropActionType.move); de.moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean): boolean => { - //this.clearDoc(which); return addDocument(doc); }; de.canEmbed = true; @@ -181,15 +191,24 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() remDoc2 = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((res, doc) => res && this.remDoc(doc, this.fieldKey + '_2'), true); _closeRef = React.createRef<HTMLDivElement>(); + /** + * Flips a flashcard to the alternate side for the user to view. + */ flipFlashcard = () => { const usePath = this.layoutDoc[`_${this._props.fieldKey}_usePath`]; - this.layoutDoc[`_${this._props.fieldKey}_usePath`] = usePath === undefined ? 'alternate' : undefined; }; + + /** + * Changes the view option to hover for a flashcard. + */ hoverFlip = (side: string | undefined) => { if (this.layoutDoc[`_${this._props.fieldKey}_revealOp`] == 'hover') this.layoutDoc[`_${this._props.fieldKey}_usePath`] = side; }; + /** + * Creates the button used to flip the flashcards. + */ @computed get overlayAlternateIcon() { const usepath = this.layoutDoc[`_${this._props.fieldKey}_usePath`]; return ( @@ -203,21 +222,10 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() this.flipFlashcard(); console.log('Print Front of cards: ' + RTFCast(DocCast(this.dataDoc[this.fieldKey + '_0']).text)?.Text); console.log('Print Back of cards: ' + RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text); - - //const queryText = RTFCast(DocCast(this.dataDoc[this.fieldKey + '_0']).text)?.Text; - // DocCast(this.dataDoc[this.fieldKey + '_1'])[DocData].text = 'hello'; - // const mes = gptAPICall(queryText, GPTCallType.COMPLETION).trim(); - // const res = await gptAPICall(queryText, GPTCallType.COMPLETION) - // console.log(res); - //.then(value => (DocCast(this.dataDoc[this.fieldKey + '_1']).text = value.trim())); - if (usepath !== 'alternate') { - this.askGPT(); - } } }) } style={{ - //display: this._props.isContentActive() && !SnappingManager.IsDragging ? 'flex' : 'none', background: usepath === 'alternate' ? 'white' : 'black', color: usepath === 'alternate' ? 'black' : 'white', }}> @@ -227,15 +235,34 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() ); } + @action handleRenderGPTClick = () => { + // Call the GPT model and get the output + this.layoutDoc[`_${this._props.fieldKey}_usePath`] = 'alternate'; + this.outputValue = ''; + if (this.inputValue) this.askGPT(); + }; + + @action handleRenderClick = () => { + // Call the GPT model and get the output + this.layoutDoc[`_${this._props.fieldKey}_usePath`] = undefined; + }; + + /** + * Calls the GPT model to create QuizCards. Evaluates how similar the user's response is to the alternate + * side of the flashcard. + */ askGPT = async (): Promise<string | undefined> => { - const queryText = RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text; + const questionText = 'Question: ' + StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text); + const rubricText = ' Rubric: ' + StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_0']).text)?.Text); + const queryText = questionText + ' UserAnswer: ' + this.inputValue + '. ' + rubricText; + try { - let res = await gptAPICall(StrCast(queryText), GPTCallType.COMPLETION); + let res = await gptAPICall(queryText, GPTCallType.QUIZ); if (!res) { console.error('GPT call failed'); return; } - DocCast(this.dataDoc[this.fieldKey + '_0'])[DocData].text = res; + this.outputValue = res; console.log(res); } catch (err) { console.error('GPT call failed'); @@ -292,8 +319,6 @@ 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)} @@ -326,36 +351,54 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() if (this.Document._layout_isFlashcard) { const side = this.layoutDoc[`_${this._props.fieldKey}_usePath`] === 'alternate' ? 1 : 0; - // add text box when first created + // add text box to each side when comparison box is first created if (!(this.dataDoc[this.fieldKey + '_0'] || this.dataDoc[this.fieldKey + '_0'] == 'empty')) { const dataSplit = StrCast(this.dataDoc.data).split('Answer'); const newDoc = Docs.Create.TextDocument(dataSplit[1]); + // if there is text from the pdf ai cards, put the question on the front side. newDoc[DocData].text = dataSplit[1]; this.addDoc(newDoc, this.fieldKey + '_0'); } if (!(this.dataDoc[this.fieldKey + '_1'] || this.dataDoc[this.fieldKey + '_1'] == 'empty')) { const dataSplit = StrCast(this.dataDoc.data).split('Answer'); const newDoc = Docs.Create.TextDocument(dataSplit[0]); - newDoc[DocData].text = 'placeholder...'; + // if there is text from the pdf ai cards, put the answer on the alternate side. + newDoc[DocData].text = dataSplit[0]; this.addDoc(newDoc, this.fieldKey + '_1'); } - 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)} + // render the QuizCards + if (DocCast(this.Document.embedContainer) && DocCast(this.Document.embedContainer)[`filterOp`] == 'quiz') { + return ( + <div className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}`} style={{ display: 'flex', flexDirection: 'column' }}> + <p style={{ color: 'white', padding: 10 }}>{StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text)}</p> + {/* {StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text)} */} + <div className={'input-box'}> + { + <textarea + value={this.layoutDoc[`_${this._props.fieldKey}_usePath`] === 'alternate' ? this.outputValue : this.inputValue} + onChange={this.handleInputChange} + readOnly={this.layoutDoc[`_${this._props.fieldKey}_usePath`] === 'alternate'} + /> + } </div> - ); - } - } else { + <div className="submit-button" style={{ display: this.layoutDoc[`_${this._props.fieldKey}_usePath`] === 'alternate' ? 'none' : 'flex' }}> + <button onClick={this.handleRenderGPTClick}>Submit</button> + </div> + <div className="submit-button" style={{ display: this.layoutDoc[`_${this._props.fieldKey}_usePath`] === 'alternate' ? 'flex' : 'none' }}> + <button onClick={this.handleRenderClick}>Edit Your Response</button> + </div> + </div> + ); + } + + // render a normal flashcard when not a QuizCard + 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' }} + style={{ display: 'flex', flexDirection: 'column' }} onMouseEnter={() => { this.hoverFlip('alternate'); }} @@ -363,12 +406,12 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() this.hoverFlip(undefined); }}> {displayBox(`${this.fieldKey}_${side === 0 ? 1 : 0}`, side, this._props.PanelWidth() - 3)} - {this.overlayAlternateIcon} </div> ); } } else { + // render a comparison box that compares items side by side return ( <div className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}` /* change className to easily disable/enable pointer events in CSS */}> {displayBox(`${this.fieldKey}_2`, 1, this._props.PanelWidth() - 3)} |