aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/views/collections/CollectionCarouselView.tsx51
-rw-r--r--src/client/views/nodes/ComparisonBox.scss8
-rw-r--r--src/client/views/nodes/ComparisonBox.tsx90
-rw-r--r--src/client/views/pdf/AnchorMenu.tsx13
-rw-r--r--src/client/views/pdf/Annotation.scss19
-rw-r--r--src/client/views/pdf/PDFViewer.tsx1
6 files changed, 136 insertions, 46 deletions
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index b5b6e1f4b..f2d634eaa 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -21,6 +21,8 @@ import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
import './CollectionCarouselView.scss';
import { CollectionSubView } from './CollectionSubView';
import { Tooltip } from '@mui/material';
+import { DocUtils } from '../../documents/DocUtils';
+import { Any } from '@react-spring/web';
enum cardMode {
// PRACTICE = 'practice',
@@ -49,7 +51,8 @@ export class CollectionCarouselView extends CollectionSubView() {
constructor(props: any) {
super(props);
makeObservable(this);
- // this.layoutDoc.filterOp = cardMode.ALL;
+ // this.setModes();
+ this.layoutDoc.filterOp = cardMode.ALL;
Doc.setDocFilter(this.Document, 'data_star', undefined, 'match');
this.layoutDoc.practiceMode = practiceMode.NORMAL;
this.layoutDoc._carousel_index = 0;
@@ -67,6 +70,9 @@ export class CollectionCarouselView extends CollectionSubView() {
};
@computed get carouselItems() {
+ this.childLayoutPairs.map(pair => {
+ pair.layout.embedContainer = this.Document;
+ });
return this.childLayoutPairs.filter(pair => pair.layout.type !== DocumentType.LINK);
}
@computed get marginX() {
@@ -80,6 +86,13 @@ export class CollectionCarouselView extends CollectionSubView() {
this._filterMessage = mes;
};
+ setModes = () => {
+ this.layoutDoc.filterOp = cardMode.ALL;
+ Doc.setDocFilter(this.Document, 'data_star', undefined, 'match');
+ this.layoutDoc.practiceMode = practiceMode.NORMAL;
+ this.layoutDoc._carousel_index = 0;
+ };
+
move = (dir: number) => {
const moveToCardWithField = (match: (doc: Doc) => boolean): boolean => {
let startInd = (NumCast(this.layoutDoc._carousel_index) + dir) % this.carouselItems.length;
@@ -107,8 +120,8 @@ export class CollectionCarouselView extends CollectionSubView() {
break;
case practiceMode.PRACTICE && cardMode.STAR:
if (!moveToCardWithField((doc: Doc) => doc[this.practiceField] !== practiceVal.CORRECT && doc[this.starField] === true)) {
- this._filterMessage = 'No flashcards to show! Unselect star mode to view all flashcards.';
- this._practiceMessage = 'Unselect practice mode to view all flashcards.';
+ this._filterMessage = 'No flashcards to show! Unselect mode to view all flashcards.';
+ this._practiceMessage = undefined;
}
break;
default:
@@ -179,20 +192,24 @@ export class CollectionCarouselView extends CollectionSubView() {
this.layoutDoc.filterOp = mode;
switch (mode) {
case cardMode.STAR:
- Doc.setDocFilter(this.Document, 'data_star', true, 'match');
+ // Doc.setDocFilter(this.Document, 'data_star', true, 'match');
this.move(1);
break;
default:
this.setFilterMessage(undefined); // prettier-ignore
- Doc.setDocFilter(this.Document, 'data_star', true, 'remove');
+ // Doc.setDocFilter(this.Document, 'data_star', true, 'remove');
}
};
@computed get content() {
+ if (this.layoutDoc._carousel_index === this.carouselItems.length && this.layoutDoc._carousel_index !== 0) {
+ this.move(1);
+ }
const index = NumCast(this.layoutDoc._carousel_index);
const curDoc = this.carouselItems?.[index];
const captionProps = { ...this._props, NativeScaling: returnOne, PanelWidth: this.captionWidth, fieldKey: 'caption', setHeight: undefined, setContentView: undefined };
const carouselShowsCaptions = StrCast(this.layoutDoc._layout_showCaption);
+
return !(curDoc?.layout instanceof Doc) ? null : (
<>
<div className="collectionCarouselView-image" key="image">
@@ -207,6 +224,7 @@ export class CollectionCarouselView extends CollectionSubView() {
onClickScript={this.onContentClick}
isDocumentActive={this._props.childDocumentsActive?.() ? this._props.isDocumentActive : this._props.isContentActive}
isContentActive={this._props.childContentsActive ?? this._props.isContentActive() === false ? returnFalse : emptyFunction}
+ addDocument={this._props.addDocument}
hideCaptions={!!carouselShowsCaptions} // hide captions if the carousel is configured to show the captions
renderDepth={this._props.renderDepth + 1}
LayoutTemplate={this._props.childLayoutTemplate}
@@ -235,12 +253,21 @@ export class CollectionCarouselView extends CollectionSubView() {
}
containsDifTypes = (): boolean => {
- return this.carouselItems.filter(doc => !doc.layout.isFlashcard).length === 0;
+ return this.carouselItems.filter(doc => !doc.layout._layout_isFlashcard).length !== 0;
};
addFlashcard() {
const newDoc = Docs.Create.ComparisonDocument('', { _layout_isFlashcard: true, _width: 300, _height: 300 });
this.addDocument?.(newDoc);
+ // DocUtils.copyDragFactory(newDoc);
+ // this._props.addDocument?.();
+ // newDoc.layout = this.layoutDoc;
+ // newDoc.data = this.dataDoc;
+ // Doc.AddDocToList()
+ // this._props.parent._props.addDocument();
+ // this.childLayoutPairs.push({ newDoc.layout, newDoc.data});
+ // this._props.addDocument?.(newDoc);
+ // console.log('HERE');
}
@computed get buttons() {
@@ -260,11 +287,11 @@ export class CollectionCarouselView extends CollectionSubView() {
<FontAwesomeIcon icon="star" color={this.carouselItems?.[NumCast(this.layoutDoc._carousel_index)].layout[this.starField] ? 'yellow' : 'gray'} size="1x" />
</div>
</Tooltip>
- <Tooltip title="add new flashcard to pile">
+ {/* <Tooltip title="add new flashcard to pile">
<div key="add" className="carouselView-add" onClick={this.addFlashcard}>
<FontAwesomeIcon icon="plus" color={this.carouselItems?.[NumCast(this.layoutDoc._carousel_index)].layout[this.starField] ? 'yellow' : 'gray'} size="1x" />
</div>
- </Tooltip>
+ </Tooltip> */}
</div>
) : null}
{this.layoutDoc.practiceMode === practiceMode.PRACTICE ? (
@@ -286,8 +313,10 @@ export class CollectionCarouselView extends CollectionSubView() {
}
togglePracticeMode = (mode: practiceMode) => {
- if (mode === this.layoutDoc.practiceMode) this.setPracticeMode(practiceMode.NORMAL);
- else this.setPracticeMode(mode);
+ if (mode === this.layoutDoc.practiceMode) {
+ this.setPracticeMode(practiceMode.NORMAL);
+ // this.setPracticeMessage("undefined");
+ } else this.setPracticeMode(mode);
};
toggleFilterMode = () => { this.layoutDoc.filterOp === cardMode.STAR ? this.setFilterMode(cardMode.ALL) : this.setFilterMode(cardMode.STAR)}; //prettier-ignore
setColor = (mode: practiceMode | cardMode, which: string) => { return which === mode ? 'white' : 'light gray'}; //prettier-ignore
@@ -351,7 +380,7 @@ export class CollectionCarouselView extends CollectionSubView() {
}}>
Recently missed!
</p>
- {!this.containsDifTypes() ? this.menu : null}
+ {!this.containsDifTypes() && this.carouselItems.length !== 0 ? this.menu : null}
{this.Document._chromeHidden || (!this._filterMessage && !this._practiceMessage) ? this.buttons : null}
</div>
);
diff --git a/src/client/views/nodes/ComparisonBox.scss b/src/client/views/nodes/ComparisonBox.scss
index 0b2c356e5..f7389e39b 100644
--- a/src/client/views/nodes/ComparisonBox.scss
+++ b/src/client/views/nodes/ComparisonBox.scss
@@ -16,14 +16,15 @@
}
.input-box {
position: absolute;
+ top: 50;
padding: 10px;
width: 100%;
- height: 100%;
+ height: 70%;
display: flex;
}
.submit-button {
- position: relative;
+ position: absolute;
padding-bottom: 10px;
padding-left: 5px;
padding-right: 5px;
@@ -31,6 +32,7 @@
border-radius: 2px;
height: 15%;
display: flex;
+ bottom: 0;
button {
flex: 1;
@@ -149,7 +151,7 @@
top: 10px;
left: 10px;
z-index: 200;
- padding: 5px;
+ // padding: 5px;
background: #dfdfdf;
}
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx
index 9eb5f6ca2..2fc297bec 100644
--- a/src/client/views/nodes/ComparisonBox.tsx
+++ b/src/client/views/nodes/ComparisonBox.tsx
@@ -28,6 +28,7 @@ import ReactLoading from 'react-loading';
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
import { tickStep } from 'd3';
+import { CollectionCarouselView } from '../collections/CollectionCarouselView';
@observer
export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@@ -46,8 +47,6 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
@observable private _isEmpty = false;
@observable _yRelativeToTop: boolean = true;
- public addToCollection: ((doc: Doc | Doc[], annotationKey?: string | undefined) => boolean) | undefined;
-
@action handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
this._inputValue = e.target.value;
console.log(this._inputValue);
@@ -248,6 +247,41 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
_closeRef = React.createRef<HTMLDivElement>();
+ 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.trim().split('Question: ');
+ var collectionArr: Doc[] = [];
+ for (let i = 1; i < senArr.length; i++) {
+ const newDoc = Docs.Create.ComparisonDocument(senArr[i].trim(), { _layout_isFlashcard: true, _width: 300, _height: 300 });
+ newDoc.text = senArr[i].trim();
+ collectionArr.push(newDoc);
+ }
+ this.createFlashcardPile(collectionArr, true);
+ };
+
/**
* Flips a flashcard to the alternate side for the user to view.
*/
@@ -305,35 +339,27 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
<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: '56px', cursor: 'pointer' }} onPointerDown={e => (!this.layoutDoc[`_${this._props.fieldKey}_usePath`] ? this.askGPT(GPTCallType.CHATCARD) : null)}>
+ <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>
- <Tooltip title={<div>Create a flashcard pile</div>}>
- <div
- style={{ position: 'absolute', bottom: '3px', right: '80px', cursor: 'pointer' }}
- onPointerDown={e => {
- // this.displayLabelHandler(e.target.value, e.clientY);
- const collectionArr: Doc[] = [];
- collectionArr.push(this.Document);
- 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;
- this._props.addDocument?.(newCol);
- this._props.removeDocument?.(this.Document);
- this.Document.embedContainer = newCol;
- }}>
- <FontAwesomeIcon icon="folder-plus" size="xl" />
+ {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>
+ )}
<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 === 'hover' ? 'blue' : 'black'} icon="layer-group" size="xl" />
+ <FontAwesomeIcon color={this.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>}>
@@ -425,6 +451,12 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
if (callType == GPTCallType.QUIZ) this._outputValue = res;
// DocCast(this.dataDoc[this.props.fieldKey + '_0'])[DocData].text = res;
// this._outputValue = res;
+
+ if (callType === GPTCallType.FLASHCARD) {
+ // console.log(res);
+ this._loading = false;
+ return res;
+ }
console.log(res);
} catch (err) {
console.error('GPT call failed');
@@ -520,7 +552,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
// 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));
+ //console.log('HEREEE' + StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_0']).text)?.Text));
}
if (!this.dataDoc[this.fieldKey + '_1'] && !this._isEmpty) {
@@ -545,7 +577,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
return (
<div className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}`} style={{ display: 'flex', flexDirection: 'column' }}>
<p style={{ color: 'white', padding: 10 }}>{text}</p>
- <p style={{ display: text === '' ? 'flex' : 'none', color: 'white', padding: 10 }}>Return to all flashcards and add text to both sides. </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.layoutDoc[`_${this._props.fieldKey}_usePath`] === 'alternate' ? this._outputValue : this._inputValue}
@@ -574,7 +606,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
);
}
- console.log('HEREEE2' + StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text));
+ //console.log('HEREEE2' + StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text));
// render a normal flashcard when not a QuizCard
return (
<div
@@ -589,7 +621,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
}}
// onPointerUp={() => (this._isAnyChildContentActive = true)}
>
- {StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text) === '' && !this.childActive ? <p className="explain">Enter text in the flashcard. </p> : null}
+ {!this.layoutDoc[`_${this._props.fieldKey}_usePath`] && StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text) === '' && !this.childActive ? <p className="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' }}>
diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx
index cedd3c7c3..c1198b4f7 100644
--- a/src/client/views/pdf/AnchorMenu.tsx
+++ b/src/client/views/pdf/AnchorMenu.tsx
@@ -15,6 +15,7 @@ import { LinkPopup } from '../linking/LinkPopup';
import { DocumentView } from '../nodes/DocumentView';
import './AnchorMenu.scss';
import { GPTPopup, GPTPopupMode } from './GPTPopup/GPTPopup';
+import ReactLoading from 'react-loading';
@observer
export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
@@ -24,6 +25,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
private _disposer: IReactionDisposer | undefined;
private _commentRef = React.createRef<HTMLDivElement>();
private _cropRef = React.createRef<HTMLDivElement>();
+ @observable private _loading = false;
// @observable protected _top: number = -300;
// @observable protected _left: number = -300;
@@ -110,15 +112,16 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
*/
gptFlashcards = async (e: React.PointerEvent) => {
const queryText = this._selectedText;
+ this._loading = true;
try {
const res = await gptAPICall(queryText, GPTCallType.FLASHCARD);
console.log(res);
- GPTPopup.Instance.setText(res || 'Something went wrong.');
+ // GPTPopup.Instance.setText(res || 'Something went wrong.');
this.transferToFlashcard(res || 'Something went wrong');
} catch (err) {
console.error(err);
}
- GPTPopup.Instance.setLoading(false);
+ // GPTPopup.Instance.setLoading(false);
};
/*
@@ -147,6 +150,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
newCol.zIndex = 100;
this.addToCollection?.(newCol);
+ this._loading = false;
};
pointerDown = (e: React.PointerEvent) => {
@@ -263,6 +267,11 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
/>
</div>
)}
+ {this._loading ? (
+ <div className="loading-spinner" style={{ position: 'absolute' }}>
+ <ReactLoading type="spin" height={30} width={30} color={'white'} />
+ </div>
+ ) : null}
</>
) : (
<>
diff --git a/src/client/views/pdf/Annotation.scss b/src/client/views/pdf/Annotation.scss
index 1de60ffed..329819ea2 100644
--- a/src/client/views/pdf/Annotation.scss
+++ b/src/client/views/pdf/Annotation.scss
@@ -7,4 +7,21 @@
&:hover {
cursor: pointer;
}
-} \ No newline at end of file
+}
+.loading-spinner {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 90%;
+ width: 93%;
+ left: 10;
+ font-size: 20px;
+ font-weight: bold;
+ color: #0b0a0a;
+}
+
+@keyframes spin {
+ to {
+ transform: rotate(360deg);
+ }
+}
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 92f890e70..af7a5774d 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -464,6 +464,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
this._mainCont.current!.style.transform = '';
}
this._selectionContent = selRange.cloneContents();
+
this._selectionText = this._selectionContent?.textContent || '';
// clear selection