aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eslint.config.mjs2
-rw-r--r--src/client/views/nodes/ComparisonBox.tsx82
2 files changed, 37 insertions, 47 deletions
diff --git a/eslint.config.mjs b/eslint.config.mjs
index aebdc20d0..f7063caa5 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -48,7 +48,7 @@ export default [
'no-return-assign': 'error',
'no-await-in-loop': 'error',
'no-loop-func': 'error',
- '@typescript-eslint/no-cond-assign': 'error',
+ 'no-cond-assign': 'error',
'no-use-before-define': 'error',
'@typescript-eslint/no-explicit-any': 'error',
'no-restricted-globals': ['error', 'event'],
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx
index 9ac8d7c52..cc20f0c57 100644
--- a/src/client/views/nodes/ComparisonBox.tsx
+++ b/src/client/views/nodes/ComparisonBox.tsx
@@ -1,41 +1,34 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { MathJax, MathJaxContext } from 'better-react-mathjax';
import { Tooltip } from '@mui/material';
+import axios from 'axios';
import { action, computed, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { returnFalse, returnNone, returnTrue, returnZero, setupMoveUpEvents } from '../../../ClientUtils';
+import ReactLoading from 'react-loading';
+import { returnFalse, returnNone, returnTrue, setupMoveUpEvents } from '../../../ClientUtils';
import { emptyFunction } from '../../../Utils';
import { Doc, Opt } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
+import { Id } from '../../../fields/FieldSymbols';
import { RichTextField } from '../../../fields/RichTextField';
import { DocCast, NumCast, RTFCast, StrCast, toList } from '../../../fields/Types';
+import { nullAudio } from '../../../fields/URLField';
import { GPTCallType, gptAPICall, gptImageLabel } from '../../apis/gpt/GPT';
-import '../pdf/GPTPopup/GPTPopup.scss';
-import { DocUtils } from '../../documents/DocUtils';
+import { DocUtils, FollowLinkScript } from '../../documents/DocUtils';
import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
import { Docs } from '../../documents/Documents';
import { DragManager } from '../../util/DragManager';
import { dropActionType } from '../../util/DropActionTypes';
import { undoable } from '../../util/UndoManager';
+import { ContextMenu } from '../ContextMenu';
import { ViewBoxAnnotatableComponent } from '../DocComponent';
import { PinDocView, PinProps } from '../PinFuncs';
import { StyleProp } from '../StyleProp';
+import '../pdf/GPTPopup/GPTPopup.scss';
import './ComparisonBox.scss';
import { DocumentView } from './DocumentView';
import { FieldView, FieldViewProps } from './FieldView';
import { FormattedTextBox } from './formattedText/FormattedTextBox';
-import ReactLoading from 'react-loading';
-import { ContextMenu } from '../ContextMenu';
-import { ContextMenuProps } from '../ContextMenuItem';
-import { tickStep } from 'd3';
-import { CollectionCarouselView } from '../collections/CollectionCarouselView';
-import { FollowLinkScript } from '../../documents/DocUtils';
-import { schema } from '../nodes/formattedText/schema_rts';
-import { Id } from '../../../fields/FieldSymbols';
-import axios from 'axios';
-import ReactMarkdown from 'react-markdown';
-import { WebField, nullAudio } from '../../../fields/URLField';
const API_URL = 'https://api.unsplash.com/search/photos';
@@ -118,26 +111,26 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
<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={e => (!this.frontSide ? this.findImageTags() : null)}>
+ <div style={{ position: 'absolute', bottom: '3px', right: '50px', cursor: 'pointer' }} onPointerDown={() => (!this.frontSide ? this.findImageTags() : null)}>
<FontAwesomeIcon icon="lightbulb" size="xl" />
</div>
</Tooltip>
{DocCast(this.Document.embedContainer)?.type_collection === CollectionViewType.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)}>
+ <div style={{ position: 'absolute', bottom: '3px', right: '74px', cursor: 'pointer' }} onPointerDown={() => 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()}>
+ <div style={{ position: 'absolute', bottom: '3px', right: '104px', cursor: 'pointer' }} onClick={() => 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()}>
+ <div style={{ position: 'absolute', bottom: '3px', right: '25px', cursor: 'pointer' }} onClick={() => this.handleHover()}>
<FontAwesomeIcon color={this.revealOp === 'hover' ? 'blue' : 'black'} icon="hand-point-up" size="xl" />
</div>
</Tooltip>
@@ -354,13 +347,13 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
openContextMenu = (x: number, y: number, evalu: boolean) => {
ContextMenu.Instance.clearItems();
- ContextMenu.Instance.addItem({ description: 'English', event: e => this.setLanguage('en-US', 0), icon: 'question' }); //prettier-ignore
- ContextMenu.Instance.addItem({ description: 'Spanish', event: e => this.setLanguage('es-ES', 1 ), icon: 'question'}); //prettier-ignore
- ContextMenu.Instance.addItem({ description: 'French', event: e => this.setLanguage('fr-FR', 2), icon: 'question' }); //prettier-ignore
- ContextMenu.Instance.addItem({ description: 'Italian', event: e => this.setLanguage('it-IT', 3), icon: 'question' }); //prettier-ignore
- if (!evalu) ContextMenu.Instance.addItem({ description: 'Mandarin Chinese', event: e => this.setLanguage('zh-CH', 4), icon: 'question' }); //prettier-ignore
- ContextMenu.Instance.addItem({ description: 'Japanese', event: e => this.setLanguage('ja', 5), icon: 'question' }); //prettier-ignore
- ContextMenu.Instance.addItem({ description: 'Korean', event: e => this.setLanguage('ko', 6), icon: 'question' }); //prettier-ignore
+ ContextMenu.Instance.addItem({ description: 'English', event: () => this.setLanguage('en-US', 0), icon: 'question' }); //prettier-ignore
+ ContextMenu.Instance.addItem({ description: 'Spanish', event: () => this.setLanguage('es-ES', 1 ), icon: 'question'}); //prettier-ignore
+ ContextMenu.Instance.addItem({ description: 'French', event: () => this.setLanguage('fr-FR', 2), icon: 'question' }); //prettier-ignore
+ ContextMenu.Instance.addItem({ description: 'Italian', event: () => this.setLanguage('it-IT', 3), icon: 'question' }); //prettier-ignore
+ if (!evalu) ContextMenu.Instance.addItem({ description: 'Mandarin Chinese', event: () => this.setLanguage('zh-CH', 4), icon: 'question' }); //prettier-ignore
+ ContextMenu.Instance.addItem({ description: 'Japanese', event: () => this.setLanguage('ja', 5), icon: 'question' }); //prettier-ignore
+ ContextMenu.Instance.addItem({ description: 'Korean', event: () => this.setLanguage('ko', 6), icon: 'question' }); //prettier-ignore
ContextMenu.Instance.displayMenu(x, y);
};
@@ -387,7 +380,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
};
getYouTubeVideoId = (url: string) => {
- const regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=|\?v=)([^#\&\?]*).*/;
+ 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;
};
@@ -418,7 +411,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
newCol['x'] = this.layoutDoc['x'];
newCol['y'] = NumCast(this.layoutDoc['y']) + 50;
newCol.type_collection = 'carousel';
- for (var i = 0; i < collectionArr.length; i++) {
+ for (let i = 0; i < collectionArr.length; i++) {
DocCast(collectionArr[i])[DocData].embedContainer = newCol;
}
@@ -436,10 +429,10 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
* Transfers the content of flashcards into a flashcard pile.
*/
gptFlashcardPile = async () => {
- var text = await this.askGPT(GPTCallType.STACK);
- var senArr = text?.split('Question: ');
- var collectionArr: Doc[] = [];
- for (let i = 1; i < senArr?.length!; i++) {
+ const text = await this.askGPT(GPTCallType.STACK);
+ const senArr = text?.split('Question: ') ?? [];
+ const collectionArr: Doc[] = [];
+ for (let i = 1; i < senArr.length; i++) {
const newDoc = Docs.Create.ComparisonDocument(senArr![i], { _layout_isFlashcard: true, _width: 300, _height: 300 });
if (StrCast(senArr![i]).includes('Keyword: ')) {
@@ -481,11 +474,10 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
* Calls GPT for each flashcard type.
*/
askGPT = async (callType: GPTCallType): Promise<string | undefined> => {
- let questionText = 'Question: ' + StrCast(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;
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) === '') {
@@ -511,11 +503,12 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
this._loading = false;
return res;
} else if (callType === GPTCallType.STACK) {
+ /* empty */
}
this._loading = false;
return res;
} catch (err) {
- console.error('GPT call failed');
+ console.error('GPT call failed', err);
}
this._loading = false;
};
@@ -527,7 +520,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
if (c?.length === 0) await this.askGPT(GPTCallType.CHATCARD);
if (c) {
this._loading = true;
- for (let i of c) {
+ for (const i of c) {
console.log(i);
if (i.className !== 'ProseMirror-separator') await this.getImageDesc(i.src);
}
@@ -653,7 +646,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
DocCast(this.dataDoc[this.props.fieldKey + '_0'])[DocData].text = response;
} catch (error) {
- console.log('Error');
+ console.log('Error', error);
}
};
@@ -692,6 +685,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
return layoutTemplateString;
};
+ childActiveFunc = () => this.childActive;
+
render() {
const clearButton = (which: string) => (
<Tooltip title={<div className="dash-tooltip">remove</div>}>
@@ -712,7 +707,6 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
return targetDoc || layoutString ? (
<>
<DocumentView
- // eslint-disable-next-line react/jsx-props-no-spreading
{...this._props}
showTags={undefined}
fitWidth={undefined}
@@ -725,7 +719,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
removeDocument={whichSlot.endsWith('1') ? this.remDoc1 : this.remDoc2}
NativeWidth={this.layoutWidth}
NativeHeight={this.layoutHeight}
- isContentActive={() => this.childActive}
+ isContentActive={this.childActiveFunc}
isDocumentActive={returnFalse}
dontSelect={returnTrue}
whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
@@ -837,13 +831,9 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
return (
<div
className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}`} /* change className to easily disable/enable pointer events in CSS */
- style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden' }}
- onMouseEnter={() => {
- this.hoverFlip(false);
- }}
- onMouseLeave={() => {
- this.hoverFlip(true);
- }}>
+ style={{ display: 'flex', flexDirection: 'column' }}
+ onMouseEnter={() => this.hoverFlip(true)}
+ onMouseLeave={() => this.hoverFlip(false)}>
{displayBox(`${this.fieldKey}_${side === 0 ? 1 : 0}`, side, this._props.PanelWidth() - 3)}
{this._loading ? (
<div className="loading-spinner" style={{ position: 'absolute' }}>