aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/ComparisonBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/ComparisonBox.tsx')
-rw-r--r--src/client/views/nodes/ComparisonBox.tsx301
1 files changed, 254 insertions, 47 deletions
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx
index efaf6807a..3e1c415d6 100644
--- a/src/client/views/nodes/ComparisonBox.tsx
+++ b/src/client/views/nodes/ComparisonBox.tsx
@@ -1,15 +1,16 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@mui/material';
-import { action, computed, makeObservable, observable } from 'mobx';
+import { action, computed, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { returnFalse, returnNone, setupMoveUpEvents } from '../../../ClientUtils';
+import { returnFalse, returnNone, returnTrue, setupMoveUpEvents } from '../../../ClientUtils';
import { emptyFunction } from '../../../Utils';
import { Doc, Opt } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
import { RichTextField } from '../../../fields/RichTextField';
import { DocCast, NumCast, RTFCast, StrCast, toList } from '../../../fields/Types';
import { GPTCallType, gptAPICall } from '../../apis/gpt/GPT';
+import '../pdf/GPTPopup/GPTPopup.scss';
import { DocUtils } from '../../documents/DocUtils';
import { DocumentType } from '../../documents/DocumentTypes';
import { Docs } from '../../documents/Documents';
@@ -23,7 +24,15 @@ import './ComparisonBox.scss';
import { DocumentView } from './DocumentView';
import { FieldView, FieldViewProps } from './FieldView';
import { FormattedTextBox } from './formattedText/FormattedTextBox';
+import ReactLoading from 'react-loading';
+enum RevealOp {
+ Hover = 'hover',
+ Flip = 'flip',
+}
+enum UsePath {
+ Alternate = 'alternate',
+}
@observer
export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
public static LayoutString(fieldKey: string) {
@@ -37,14 +46,24 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
@observable _errorMessage = '';
@observable _outputMessage = '';
@observable _animating = '';
+ @observable private _isEmpty = false;
+ @observable _yRelativeToTop: boolean = true;
constructor(props: FieldViewProps) {
super(props);
makeObservable(this);
}
+ @action handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
+ this._inputValue = e.target.value;
+ console.log(this._inputValue);
+ };
componentDidMount() {
this._props.setContentViewBox?.(this);
+ reaction(
+ () => this._props.isSelected(), // when this reaction should update
+ selected => !selected && (this.childActive = false) // what it should update to
+ );
}
protected createDropTarget = (ele: HTMLDivElement | null, fieldKey: string, disposerId: number) => {
@@ -54,11 +73,12 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
}
};
- @computed get revealOp() { return this.layoutDoc[`_${this.fieldKey}_revealOp`] as ('flip'|'hover'|undefined); } // prettier-ignore
+ @computed get useAlternate() { return this.layoutDoc[`_${this.fieldKey}_usePath`] === UsePath.Alternate; } // prettier-ignore
+ @computed get revealOp() { return this.layoutDoc[`_${this.fieldKey}_revealOp`] as Opt<RevealOp>; } // prettier-ignore
@computed get clipWidth() { return NumCast(this.layoutDoc[`_${this.fieldKey}_clipWidth`], 50); } // prettier-ignore
+ set useAlternate(alt: boolean) { this.layoutDoc[`_${this.fieldKey}_usePath`] = alt ? UsePath.Alternate : undefined; } // prettier-ignore
+ set revealOp(op: Opt<RevealOp>){ this.layoutDoc[`_${this.fieldKey}_revealOp`] = op; } // prettier-ignore
set clipWidth(width: number) { this.layoutDoc[`_${this.fieldKey}_clipWidth`] = width; } // prettier-ignore
- @computed get useAlternate() { return this.layoutDoc[`_${this.fieldKey}_usePath`] === 'alternate'; } // prettier-ignore
- set useAlternate(alt: boolean) { this.layoutDoc[`_${this.fieldKey}_usePath`] = alt ? 'alternate' : undefined; } // prettier-ignore
animateClipWidth = action((clipWidth: number, duration = 200 /* ms */) => {
this._animating = `all ${duration}ms`; // turn on clip animation transition, then turn it off at end of animation
@@ -73,6 +93,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
Doc.SetContainer(droppedDocuments.lastElement(), this.dataDoc);
!added && e.preventDefault();
e.stopPropagation(); // prevent parent Doc from registering new position so that it snaps back into place
+ // this.childActive = false;
return added;
}
return undefined;
@@ -87,7 +108,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
emptyFunction,
action((clickEv, doubleTap) => {
if (doubleTap) {
- this._isAnyChildContentActive = true;
+ this.childActive = true;
if (!this.dataDoc[this.fieldKey + '_1'] && !this.dataDoc[this.fieldKey]) this.dataDoc[this.fieldKey + '_1'] = DocUtils.copyDragFactory(Doc.UserDoc().emptyNote as Doc);
if (!this.dataDoc[this.fieldKey + '_2'] && !this.dataDoc[this.fieldKey + '_alternate']) this.dataDoc[this.fieldKey + '_2'] = DocUtils.copyDragFactory(Doc.UserDoc().emptyNote as Doc);
// DocumentView.addViewRenderedCb(DocCast(this.dataDoc[this.fieldKey + '_1']), dv => {
@@ -127,23 +148,29 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
};
clearDoc = undoable((fieldKey: string) => {
- delete this.dataDoc[fieldKey];
- this.dataDoc[fieldKey] = 'empty';
+ // delete this.dataDoc[fieldKey];
+ this.dataDoc[fieldKey] = undefined;
+ this._isEmpty = true;
+ // this.dataDoc[fieldKey] = 'empty';
+ console.log('HERE' + fieldKey + ';');
}, 'clear doc');
// clearDoc = (fieldKey: string) => delete this.dataDoc[fieldKey];
moveDoc = (doc: Doc, addDocument: (document: Doc | Doc[]) => boolean, which: string) => this.remDoc(doc, which) && addDocument(doc);
addDoc = (doc: Doc, which: string) => {
- if (this.dataDoc[which] && this.dataDoc[which] !== 'empty') return false;
+ if (this.dataDoc[which] && !this._isEmpty) return false;
this.dataDoc[which] = doc;
return true;
};
remDoc = (doc: Doc, which: string) => {
if (this.dataDoc[which] === doc) {
+ this._isEmpty = true;
// this.dataDoc[which] = 'empty';
+ console.log('HEREEEE');
this.dataDoc[which] = undefined;
return true;
}
+ console.log('FALSE');
return false;
};
@@ -205,6 +232,41 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
return layoutTemplateString;
};
+ createFlashcardPile(collectionArr: Doc[], gpt: boolean) {
+ const newCol = Docs.Create.CarouselDocument(collectionArr, {
+ _width: NumCast(this.layoutDoc['_' + this._props.fieldKey + '_width'], 250) + 50,
+ _height: NumCast(this.layoutDoc['_' + this._props.fieldKey + '_width'], 200) + 50,
+ _layout_fitWidth: false,
+ _layout_autoHeight: true,
+ });
+ newCol['x'] = this.layoutDoc['x'];
+ newCol['y'] = NumCast(this.layoutDoc['y']) + 50;
+ newCol.type_collection = 'carousel';
+ // console.log(newCol.data);
+
+ if (gpt) {
+ this._props.DocumentView?.()._props.addDocument?.(newCol);
+ this._props.removeDocument?.(this.Document);
+ } else {
+ this._props.addDocument?.(newCol);
+ this._props.removeDocument?.(this.Document);
+ this.Document.embedContainer = newCol;
+ }
+ }
+
+ gptFlashcardPile = async () => {
+ var text = await this.askGPT(GPTCallType.FLASHCARD);
+
+ var senArr = text?.split('Question: ');
+ var collectionArr: Doc[] = [];
+ for (let i = 1; i < senArr?.length!; i++) {
+ const newDoc = Docs.Create.ComparisonDocument(senArr![i], { _layout_isFlashcard: true, _width: 300, _height: 300 });
+ newDoc.text = senArr![i];
+ collectionArr.push(newDoc);
+ }
+ this.createFlashcardPile(collectionArr, true);
+ };
+
/**
* Flips a flashcard to the alternate side for the user to view.
*/
@@ -216,9 +278,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
* Changes the view option to hover for a flashcard.
*/
hoverFlip = (alternate: boolean) => {
- if (this.revealOp === 'hover') this.useAlternate = alternate;
+ if (this.revealOp === RevealOp.Hover) this.useAlternate = alternate;
};
-
/**
* Creates the button used to flip the flashcards.
*/
@@ -229,10 +290,11 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
className="formattedTextBox-alternateButton"
onPointerDown={e =>
setupMoveUpEvents(e.target, e, returnFalse, emptyFunction, () => {
- if (!this.revealOp || this.revealOp === 'flip') {
+ if (!this.revealOp || this.revealOp === RevealOp.Flip) {
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 ?? ''));
+
+ // 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 ?? ''));
}
})
}
@@ -240,17 +302,73 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
background: this.useAlternate ? 'white' : 'black',
color: this.useAlternate ? 'black' : 'white',
}}>
- <FontAwesomeIcon icon="turn-up" size="sm" />
+ <div key="alternate" className="formattedTextBox-flip">
+ <FontAwesomeIcon icon="turn-up" size="1x" />
+ </div>
</div>
</Tooltip>
);
}
+ @computed get flashcardMenu() {
+ return (
+ <div>
+ <Tooltip
+ title={this.useAlternate ? <div className="dash-tooltip">Flip to front side to use GPT</div> : <div className="dash-tooltip">Ask GPT to create an answer on the back side of the flashcard based on your question on the front</div>}>
+ <div style={{ position: 'absolute', bottom: '3px', right: '50px', cursor: 'pointer' }} onPointerDown={e => (!this.layoutDoc[`_${this._props.fieldKey}_usePath`] ? this.askGPT(GPTCallType.CHATCARD) : null)}>
+ <FontAwesomeIcon icon="lightbulb" size="xl" />
+ </div>
+ </Tooltip>
+ {DocCast(this.Document.embedContainer).type_collection === 'carousel' ? null : (
+ <div>
+ <Tooltip title={<div>Create a flashcard pile</div>}>
+ <div style={{ position: 'absolute', bottom: '3px', right: '74px', cursor: 'pointer' }} onPointerDown={e => this.createFlashcardPile([this.Document], false)}>
+ <FontAwesomeIcon icon="folder-plus" size="xl" />
+ </div>
+ </Tooltip>
+ <Tooltip title={<div className="dash-tooltip">Create new flashcard stack based on text</div>}>
+ <div style={{ position: 'absolute', bottom: '3px', right: '104px', cursor: 'pointer' }} onClick={e => this.gptFlashcardPile()}>
+ <FontAwesomeIcon icon="layer-group" size="xl" />
+ </div>
+ </Tooltip>
+ </div>
+ )}
+ <Tooltip title={<div className="dash-tooltip">Hover to reveal</div>}>
+ <div style={{ position: 'absolute', bottom: '3px', right: '25px', cursor: 'pointer' }} onClick={e => this.handleHover()}>
+ <FontAwesomeIcon color={this.revealOp === RevealOp.Hover ? 'blue' : 'black'} icon="hand-point-up" size="xl" />
+ </div>
+ </Tooltip>
+ {/* <Tooltip title={<div className="dash-tooltip">Remove this side of the flashcard</div>}>
+ <div
+ style={{ position: 'absolute', bottom: '3px', right: '80px', cursor: 'pointer' }}
+ onPointerDown={e => this.closeDown(e, this.layoutDoc[`_${this._props.fieldKey}_usePath`] === 'alternate' ? this._props.fieldKey + '_1' : this._props.fieldKey + '_0')}>
+ <FontAwesomeIcon color={this.revealOp === 'hover' ? 'blue' : 'black'} icon="trash-can" size="xl" />
+ </div>
+ </Tooltip> */}
+ {/* {this.overlayAlternateIcon} */}
+ </div>
+ );
+ }
+ // this.closeDown(e, this.layoutDoc[`_${this._props.fieldKey}_usePath`] === 'alternate' ? this.fieldKey + '_0' : this.fieldKey + '_1')}
+ @action activateContent = () => {
+ this.childActive = true;
+ };
+
@action handleRenderGPTClick = () => {
// Call the GPT model and get the output
this.useAlternate = true;
this._outputValue = '';
- if (this._inputValue) this.askGPT();
+ if (this._inputValue) this.askGPT(GPTCallType.QUIZ);
+ };
+
+ @action handleHover = () => {
+ if (this.revealOp === RevealOp.Hover) {
+ this.revealOp = RevealOp.Flip;
+ this.Document.forceActive = false;
+ } else {
+ this.revealOp = RevealOp.Hover;
+ this.Document.forceActive = true;
+ }
};
@action handleRenderClick = () => {
@@ -258,38 +376,86 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
this.useAlternate = false;
};
+ animateRes = (resIndex: number, newText: string, callType: GPTCallType) => {
+ if (resIndex < newText.length) {
+ // const marks = this._editorView?.state.storedMarks ?? [];
+ switch (callType) {
+ case GPTCallType.CHATCARD:
+ DocCast(this.dataDoc[this.props.fieldKey + '_0'])[DocData].text += newText[resIndex];
+ break;
+ case GPTCallType.QUIZ:
+ this._outputValue += newText[resIndex];
+ break;
+ default:
+ return;
+ }
+
+ // this._editorView?.dispatch(this._editorView?.state.tr.insertText(newText[resIndex]).setStoredMarks(this._outputValue));
+ setTimeout(() => this.animateRes(resIndex + 1, newText, callType), 20);
+ }
+ };
+
/**
* 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> => {
+ askGPT = async (callType: GPTCallType): Promise<string | undefined> => {
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;
-
+ this._loading = true;
+ const doc = DocCast(this.dataDoc[this.props.fieldKey + '_0']);
+ if (callType == GPTCallType.CHATCARD) {
+ if (StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text) === '') {
+ this._loading = false;
+ return;
+ }
+ this.flipFlashcard();
+ }
try {
- const res = await gptAPICall(queryText, GPTCallType.QUIZ);
+ const res = await gptAPICall(callType == GPTCallType.QUIZ ? queryText : questionText, callType);
if (!res) {
console.error('GPT call failed');
return;
}
- this._outputValue = res;
+ // this.animateRes(0, res, callType);
+ if (callType == GPTCallType.CHATCARD) {
+ DocCast(this.dataDoc[this.props.fieldKey + '_0'])[DocData].text = res;
+ // this.flipFlashcard();
+ }
+ if (callType == GPTCallType.QUIZ) this._outputValue = res;
+ // DocCast(this.dataDoc[this.props.fieldKey + '_0'])[DocData].text = res;
+ // this._outputValue = res;
+ else if (callType === GPTCallType.FLASHCARD) {
+ // console.log(res);
+ this._loading = false;
+ return res;
+ }
+ // console.log(res);
} catch (err) {
console.error('GPT call failed');
}
+ this._loading = false;
};
layoutWidth = () => NumCast(this.layoutDoc.width, 200);
layoutHeight = () => NumCast(this.layoutDoc.height, 200);
+ // specificMenu = (): void => {
+ // const cm = ContextMenu.Instance;
+ // cm.addItem({ description: 'Create an Answer on the Back', event: () => this.askGPT(GPTCallType.CHATCARD), icon: 'pencil' });
+ // };
+ @observable childActive = false;
+
render() {
const clearButton = (which: string) => (
<Tooltip title={<div className="dash-tooltip">remove</div>}>
<div
+ // style={{ position: 'relative', top: '0px', left: '10px' }}
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" />
+ <FontAwesomeIcon className={`clear-button ${which}`} icon="times" size="xs" />
</div>
</Tooltip>
);
@@ -297,6 +463,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
const whichDoc = DocCast(this.dataDoc[whichSlot]);
const targetDoc = DocCast(whichDoc?.annotationOn, whichDoc);
const layoutString = targetDoc ? '' : this.testForTextFields(whichSlot);
+ // whichDoc['backgroundColor'] = this.layoutDoc['backgroundColor'];
return targetDoc || layoutString ? (
<>
@@ -312,15 +479,16 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
removeDocument={whichSlot.endsWith('1') ? this.remDoc1 : this.remDoc2}
NativeWidth={this.layoutWidth}
NativeHeight={this.layoutHeight}
- isContentActive={emptyFunction}
+ isContentActive={() => this.childActive}
isDocumentActive={returnFalse}
+ dontSelect={returnTrue}
whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
- styleProvider={this._isAnyChildContentActive ? this._props.styleProvider : this.docStyleProvider}
+ styleProvider={this.childActive ? this._props.styleProvider : this.docStyleProvider}
hideLinkButton
- pointerEvents={this._isAnyChildContentActive ? undefined : returnNone}
+ pointerEvents={this.childActive ? undefined : returnNone}
/>
- {layoutString ? null : clearButton(whichSlot)}
- </> // placeholder image if doc is missing
+ {/* <div style={{ position: 'absolute', top: '-5px', left: '2px' }}>{layoutString ? null : clearButton(whichSlot)}</div> */}
+ </> // placeholder image if doc is missingleft: `${NumCast(this.layoutDoc.width, 200) - 33}px`
) : (
<div className="placeholder">
<FontAwesomeIcon className="upload-icon" icon="cloud-upload-alt" size="lg" />
@@ -328,8 +496,17 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
);
};
const displayBox = (which: string, index: number, cover: number) => (
- <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)}
+ <div
+ className={`${index === 0 ? 'before' : 'after'}Box-cont`}
+ key={which}
+ style={{ width: this._props.PanelWidth() }}
+ onPointerDown={e => {
+ this.registerSliding(e, cover);
+ this.activateContent();
+ }}
+ ref={ele => this.createDropTarget(ele, which, index)}>
+ {!this._isEmpty ? displayDoc(which) : null}
+ {/* {this.dataDoc[this.fieldKey + '_0'] !== 'empty' ? displayDoc(which) : null} */}
</div>
);
@@ -337,60 +514,90 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
const side = this.useAlternate ? 1 : 0;
// 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');
+ // (!this.dataDoc[this.fieldKey + '_0'] && this.dataDoc[this._props.fieldKey + '_0'] !== 'empty')
+ if (!this.dataDoc[this.fieldKey + '_0'] && !this._isEmpty) {
+ 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.
// eslint-disable-next-line prefer-destructuring
- newDoc[DocData].text = dataSplit[1];
+ // newDoc.text = dataSplit[1];
+ newDoc['backgroundColor'] = 'lightgray';
this.addDoc(newDoc, this.fieldKey + '_0');
+ // DocCast(this.dataDoc[this.fieldKey + '_0'])[DocData].text = dataSplit[1];
+ // DocCast(this.dataDoc[this.fieldKey + '_0']).text = dataSplit[1];
+ // console.log('HI' + DocCast(this.dataDoc[this.fieldKey + '_0']).text);
+ //console.log('HEREEE' + StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_0']).text)?.Text));
}
- if (!(this.dataDoc[this.fieldKey + '_1'] || this.dataDoc[this.fieldKey + '_1'] === 'empty')) {
- const dataSplit = StrCast(this.dataDoc.data).split('Answer');
+
+ if (!this.dataDoc[this.fieldKey + '_1'] && !this._isEmpty) {
+ const dataSplit = StrCast(this.dataDoc.data).split('Answer: ');
const newDoc = Docs.Create.TextDocument(dataSplit[0]);
+ this.addDoc(newDoc, this.fieldKey + '_1');
// if there is text from the pdf ai cards, put the answer on the alternate side.
// eslint-disable-next-line prefer-destructuring
- newDoc[DocData].text = dataSplit[0];
- this.addDoc(newDoc, this.fieldKey + '_1');
+
+ // newDoc[DocData].text = dataSplit[0];
+ // console.log('HEREEE' + StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text));
+ // console.log('HI' + DocCast(this.dataDoc[this.fieldKey + '_1']).text);
+ // DocCast(this.dataDoc[this.props.fieldKey + '_1'])[DocData].text = dataSplit[0];
+ // console.log('HEREEE' + StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_0']).text)?.Text));
+ // DocCast(this.dataDoc[this.fieldKey + '_1'])[DocData].text = dataSplit[0];
}
// render the QuizCards
- if (DocCast(this.Document.embedContainer) && DocCast(this.Document.embedContainer).filterOp === 'quiz') {
+ // console.log('GERE' + DocCast(this.Document.embedContainer).filterOp);
+ if (DocCast(this.Document.embedContainer) && DocCast(this.Document.embedContainer).practiceMode === 'quiz') {
+ const text = StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text);
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)} */}
+ <p style={{ color: 'white', padding: 10 }}>{text}</p>
+ <p style={{ display: text === '' ? 'flex' : 'none', color: 'white', marginLeft: '10px' }}>Return to all flashcards and add text to both sides. </p>
<div className="input-box">
<textarea
value={this.useAlternate ? this._outputValue : this._inputValue}
- onChange={action(e => {
- this._inputValue = e.target.value;
- })}
+ onChange={this.handleInputChange}
+ onScroll={e => e.stopPropagation()}
+ placeholder={!this.useAlternate ? 'Enter a response for GPT to evaluate.' : ''}
readOnly={this.useAlternate}
/>
+
+ {this._loading ? (
+ <div className="loading-spinner" style={{ position: 'absolute' }}>
+ <ReactLoading type="spin" height={30} width={30} color={'blue'} />
+ </div>
+ ) : null}
</div>
- <div className="submit-button" style={{ display: this.useAlternate ? 'none' : 'flex' }}>
- <button type="button" onClick={this.handleRenderGPTClick}>
+ <div className="submit-button" style={{ overflow: 'hidden', display: this.useAlternate ? 'none' : 'flex' }}>
+ <button type="button" onClick={this.handleRenderGPTClick} style={{ borderRadius: '2px', marginBottom: '3px' }}>
Submit
</button>
</div>
- <div className="submit-button" style={{ display: this.useAlternate ? 'flex' : 'none' }}>
- <button type="button" onClick={this.handleRenderClick}>
- Edit Your Response
+ <div className="submit-button" style={{ overflow: 'hidden', marginBottom: '2px', display: this.useAlternate ? 'flex' : 'none' }}>
+ <button type="button" onClick={this.handleRenderClick} style={{ borderRadius: '2px' }}>
+ Redo the Question
</button>
</div>
</div>
);
}
+ //console.log('HEREEE2' + StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text));
// render a normal flashcard when not a QuizCard
return (
<div
className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}`} /* change className to easily disable/enable pointer events in CSS */
- style={{ display: 'flex', flexDirection: 'column' }}
+ // onContextMenu={this.specificMenu}
+ style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden' }}
onMouseEnter={() => this.hoverFlip(true)}
onMouseLeave={() => this.hoverFlip(false)}>
+ {!this.useAlternate && StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text) === '' && !this.childActive ? <p className="comparisonBox-explain">Enter text in the flashcard. </p> : null}
{displayBox(`${this.fieldKey}_${side === 0 ? 1 : 0}`, side, this._props.PanelWidth() - 3)}
+ {this._loading ? (
+ <div className="loading-spinner" style={{ position: 'absolute' }}>
+ <ReactLoading type="spin" height={30} width={30} color={'blue'} />
+ </div>
+ ) : null}
+ {this._props.isContentActive() ? this.flashcardMenu : null}
{this.overlayAlternateIcon}
</div>
);