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.tsx157
1 files changed, 51 insertions, 106 deletions
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx
index cc20f0c57..d2a032d79 100644
--- a/src/client/views/nodes/ComparisonBox.tsx
+++ b/src/client/views/nodes/ComparisonBox.tsx
@@ -1,11 +1,11 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@mui/material';
import axios from 'axios';
-import { action, computed, makeObservable, observable, reaction } from 'mobx';
+import { IReactionDisposer, action, computed, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import ReactLoading from 'react-loading';
-import { returnFalse, returnNone, returnTrue, setupMoveUpEvents } from '../../../ClientUtils';
+import { returnFalse, returnNone, returnTrue, returnZero, setupMoveUpEvents } from '../../../ClientUtils';
import { emptyFunction } from '../../../Utils';
import { Doc, Opt } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
@@ -37,7 +37,10 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
public static LayoutString(fieldKey: string) {
return FieldView.LayoutString(ComparisonBox, fieldKey);
}
+ private SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
+ private _closeRef = React.createRef<HTMLDivElement>();
private _disposers: (DragManager.DragDropDisposer | undefined)[] = [undefined, undefined];
+ private _reactDisposer: IReactionDisposer | undefined;
constructor(props: FieldViewProps) {
super(props);
makeObservable(this);
@@ -48,38 +51,19 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
@observable private _outputValue = '';
@observable private _loading = false;
@observable private _isEmpty = false;
- @observable private _audio: Doc = Docs.Create.TextDocument('');
- @observable childActive = false;
- @observable _yRelativeToTop: boolean = true;
- @observable _animating = '';
- @observable mathJaxConfig = {
- loader: { load: ['input/asciimath'] },
- };
+ @observable private _childActive = false;
+ @observable private _animating = '';
@observable private _listening = false;
- @observable transcriptElement = '';
- @observable private frontSide = false;
- SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
+ @observable private _frontSide = false;
@observable recognition = new this.SpeechRecognition();
- _closeRef = React.createRef<HTMLDivElement>();
-
- get revealOp() {
- return this.layoutDoc[`_${this._props.fieldKey}_revealOp`];
- }
- get clipHeightKey() {
- return '_' + this._props.fieldKey + '_clipHeight';
- }
-
- get clipWidthKey() {
- return '_' + this._props.fieldKey + '_clipWidth';
- }
-
- @computed get clipWidth() {
- return NumCast(this.layoutDoc[this.clipWidthKey], 50);
- }
- @computed get clipHeight() {
- return NumCast(this.layoutDoc[this.clipHeightKey], 200);
- }
+ @computed get revealOpKey() { return `_${this._props.fieldKey}_revealOp`; } // prettier-ignore
+ @computed get clipHeightKey() { return `_${this._props.fieldKey}_clipHeight`; } // prettier-ignore
+ @computed get clipWidthKey() { return `_${this._props.fieldKey}_clipWidth`; } // prettier-ignore
+ @computed get clipWidth() { return NumCast(this.layoutDoc[this.clipWidthKey], 50); } // prettier-ignore
+ @computed get clipHeight() { return NumCast(this.layoutDoc[this.clipHeightKey], 200); } // prettier-ignore
+ @computed get revealOp() { return StrCast(this.layoutDoc[this.revealOpKey]); } // prettier-ignore
+ set revealOp(value:string) { this.layoutDoc[this.revealOpKey] = value; } // prettier-ignore
@computed get overlayAlternateIcon() {
return (
@@ -94,8 +78,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
})
}
style={{
- background: this.revealOp === 'hover' ? 'gray' : this.frontSide ? 'white' : 'black',
- color: this.revealOp === 'hover' ? 'black' : this.frontSide ? 'black' : 'white',
+ background: this.revealOp === 'hover' ? 'gray' : this._frontSide ? 'white' : 'black',
+ color: this.revealOp === 'hover' ? 'black' : this._frontSide ? 'black' : 'white',
display: 'inline-block',
}}>
<div key="alternate" className="formattedTextBox-flip">
@@ -110,8 +94,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
return (
<div>
<Tooltip
- title={this.frontSide ? <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={() => (!this.frontSide ? this.findImageTags() : null)}>
+ title={this._frontSide ? <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={() => (!this._frontSide ? this.findImageTags() : null)}>
<FontAwesomeIcon icon="lightbulb" size="xl" />
</div>
</Tooltip>
@@ -140,40 +124,37 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
@action handleHover = () => {
if (this.revealOp === 'hover') {
- this.layoutDoc[`_${this._props.fieldKey}_revealOp`] = 'flip';
+ this.revealOp = 'flip';
this.Document.forceActive = false;
} else {
- this.layoutDoc[`_${this._props.fieldKey}_revealOp`] = 'hover';
+ this.revealOp = 'hover';
this.Document.forceActive = true;
}
};
@action handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
this._inputValue = e.target.value;
- console.log(this._inputValue);
};
@action activateContent = () => {
- this.childActive = true;
+ this._childActive = true;
};
@action handleRenderClick = () => {
- this.frontSide = !this.frontSide;
+ this._frontSide = !this._frontSide;
};
@action handleRenderGPTClick = async () => {
const phonTrans = DocCast(this.Document.audio) ? DocCast(this.Document.audio).phoneticTranscription : undefined;
if (phonTrans) {
this._inputValue = StrCast(phonTrans);
- console.log('INPUT:' + this._inputValue);
this.askGPTPhonemes(this._inputValue);
} else if (this._inputValue) this.askGPT(GPTCallType.QUIZ);
- this.frontSide = false;
+ this._frontSide = false;
this._outputValue = '';
};
- @action
- private onPointerMove = ({ movementX }: PointerEvent) => {
+ onPointerMove = ({ movementX }: PointerEvent) => {
const width = movementX * this.ScreenToLocalBoxXf().Scale + (this.clipWidth / 100) * this._props.PanelWidth();
if (width && width > 5 && width < this._props.PanelWidth()) {
this.layoutDoc[this.clipWidthKey] = (width * 100) / this._props.PanelWidth();
@@ -183,12 +164,16 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
componentDidMount() {
this._props.setContentViewBox?.(this);
- reaction(
+ this._reactDisposer = reaction(
() => this._props.isSelected(), // when this reaction should update
- selected => !selected && (this.childActive = false) // what it should update to
+ selected => !selected && (this._childActive = false) // what it should update to
);
}
+ componentWillUnmount() {
+ this._reactDisposer?.();
+ }
+
protected createDropTarget = (ele: HTMLDivElement | null, fieldKey: string, disposerId: number) => {
this._disposers[disposerId]?.();
if (ele) {
@@ -241,7 +226,6 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
this.dataDoc[which] = undefined;
return true;
}
- console.log('FALSE');
return false;
};
@@ -271,7 +255,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
remDoc1 = (docs: Doc | Doc[]) => toList(docs).reduce((res, doc) => res && this.remDoc(doc, this.fieldKey + '_1'), true);
remDoc2 = (docs: Doc | Doc[]) => toList(docs).reduce((res, doc) => res && this.remDoc(doc, this.fieldKey + '_2'), true);
- private registerSliding = (e: React.PointerEvent<HTMLDivElement>, targetWidth: number) => {
+ registerSliding = (e: React.PointerEvent<HTMLDivElement>, targetWidth: number) => {
if (e.button !== 2) {
setupMoveUpEvents(
this,
@@ -280,7 +264,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
emptyFunction,
action((moveEv, doubleTap) => {
if (doubleTap) {
- this.childActive = 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);
}
@@ -288,7 +272,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
false,
undefined,
action(() => {
- if (this.childActive) return;
+ if (this._childActive) return;
this._animating = 'all 200ms';
// on click, animate slider movement to the targetWidth
this.layoutDoc[this.clipWidthKey] = (targetWidth * 100) / this._props.PanelWidth();
@@ -308,8 +292,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
* Set up speech to text tool.
*/
setListening = () => {
- const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
- if (SpeechRecognition) {
+ if (this.SpeechRecognition) {
this.recognition.continuous = true;
this.recognition.interimResults = true;
this.recognition.lang = 'en-US';
@@ -340,8 +323,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
case 'fr-FR': return 'French'; //prettier-ignore
case 'it-IT': return 'Italian'; //prettier-ignore
case 'zh-CH': return 'Mandarin Chinese'; //prettier-ignore
- case 'ja': return 'Japanese'; //prettier-ignore
- default: return 'Korean'; //prettier-ignore
+ case 'ja': return 'Japanese'; //prettier-ignore
+ default: return 'Korean'; //prettier-ignore
}
};
@@ -363,44 +346,6 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
this._props.DocumentView?.()._props.addDocument?.(newAudio);
};
- /**
- * Gets the transcription of an audio recording by sending the
- * recording to backend.
- */
- pushInfo = async () => {
- const audio = {
- file: this._audio.url,
- };
- const response = await axios.post('http://localhost:105/recognize/', audio, {
- headers: {
- 'Content-Type': 'application/json',
- },
- });
- this.Document.phoneticTranscription = response.data['transcription'];
- };
-
- getYouTubeVideoId = (url: string) => {
- const regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=|\?v=)([^#&?]*).*/;
- const match = url.match(regExp);
- return match && match[2].length === 11 ? match[2] : null;
- };
-
- /**
- * Gets the transcript of a youtube video by sending the video url to the backend.
- * @returns transcription of youtube recording
- */
- youtubeUpload = async () => {
- const audio = {
- file: this.getYouTubeVideoId(StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text)),
- };
- const response = await axios.post('http://localhost:105/youtube/', audio, {
- headers: {
- 'Content-Type': 'application/json',
- },
- });
- return response.data['transcription'];
- };
-
createFlashcardPile(collectionArr: Doc[], gpt: boolean) {
const newCol = Docs.Create.CarouselDocument(collectionArr, {
_width: NumCast(this.layoutDoc['_' + this._props.fieldKey + '_width'], 250) + 50,
@@ -497,7 +442,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
DocCast(this.dataDoc[this.props.fieldKey + '_0'])[DocData].text = res;
} else if (callType == GPTCallType.QUIZ) {
console.log(this._inputValue);
- this.frontSide = true;
+ this._frontSide = true;
this._outputValue = res.replace(/UserAnswer/g, "user's answer").replace(/Rubric/g, 'rubric');
} else if (callType === GPTCallType.FLASHCARD) {
this._loading = false;
@@ -652,11 +597,11 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
@action
flipFlashcard = () => {
- this.frontSide = !this.frontSide;
+ this._frontSide = !this._frontSide;
};
hoverFlip = (side: boolean) => {
- if (this.revealOp === 'hover') this.frontSide = side;
+ if (this.revealOp === 'hover') this._frontSide = side;
};
testForTextFields = (whichSlot: string) => {
@@ -685,7 +630,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
return layoutTemplateString;
};
- childActiveFunc = () => this.childActive;
+ childActiveFunc = () => this._childActive;
render() {
const clearButton = (which: string) => (
@@ -709,7 +654,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
<DocumentView
{...this._props}
showTags={undefined}
- fitWidth={undefined}
+ fitWidth={undefined} // set to returnTrue to make images fill the comparisonBox-- should be a user option
ignoreUsePath={layoutString ? true : undefined}
renderDepth={this.props.renderDepth + 1}
LayoutTemplateString={layoutString}
@@ -717,15 +662,15 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
containerViewPath={this._props.docViewPath}
moveDocument={whichSlot.endsWith('1') ? this.moveDoc1 : this.moveDoc2}
removeDocument={whichSlot.endsWith('1') ? this.remDoc1 : this.remDoc2}
- NativeWidth={this.layoutWidth}
- NativeHeight={this.layoutHeight}
+ NativeWidth={returnZero}
+ NativeHeight={returnZero}
isContentActive={this.childActiveFunc}
isDocumentActive={returnFalse}
dontSelect={returnTrue}
whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
- styleProvider={this.childActive ? this._props.styleProvider : this.docStyleProvider}
+ styleProvider={this._childActive ? this._props.styleProvider : this.docStyleProvider}
hideLinkButton
- pointerEvents={this.childActive ? undefined : returnNone}
+ pointerEvents={this._childActive ? undefined : returnNone}
/>
{!this.Document._layout_isFlashcard ? clearButton(whichSlot) : null}
</>
@@ -742,7 +687,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
style={{ width: this._props.PanelWidth() }}
onPointerDown={e => {
this.registerSliding(e, cover);
- this.activateContent();
+ this.Document._layout_isFlashcard && this.activateContent();
}}
ref={ele => this.createDropTarget(ele, which, index)}>
{!this._isEmpty ? displayDoc(which) : null}
@@ -750,7 +695,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
);
if (this.Document._layout_isFlashcard) {
- const side = this.frontSide ? 1 : 0;
+ const side = this._frontSide ? 1 : 0;
// add text box to each side when comparison box is first created
if (!this.dataDoc[this.fieldKey + '_0'] && !this._isEmpty) {
@@ -773,14 +718,14 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
<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.frontSide ? this._outputValue : this._inputValue}
+ value={this._frontSide ? this._outputValue : this._inputValue}
onChange={this.handleInputChange}
onScroll={e => {
e.stopPropagation();
e.preventDefault();
}}
placeholder={!this.layoutDoc[`_${this._props.fieldKey}_usePath`] ? 'Enter a response for GPT to evaluate.' : ''}
- readOnly={this.frontSide}></textarea>
+ readOnly={this._frontSide}></textarea>
{this._loading ? (
<div className="loading-spinner" style={{ position: 'absolute' }}>
@@ -812,7 +757,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
Evaluate Pronunciation
</button>
- {!this.frontSide ? (
+ {!this._frontSide ? (
<button className="submit-buttonsubmit" type="button" onClick={this.handleRenderGPTClick} style={{ borderRadius: '2px', marginBottom: '3px', width: '100%' }}>
Submit
</button>