aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/views/collections/CollectionCarouselView.scss11
-rw-r--r--src/client/views/collections/CollectionCarouselView.tsx55
-rw-r--r--src/client/views/nodes/ComparisonBox.scss13
-rw-r--r--src/client/views/nodes/ComparisonBox.tsx62
-rw-r--r--src/client/views/pdf/AnchorMenu.tsx21
-rw-r--r--src/client/views/pdf/PDFViewer.tsx1
6 files changed, 124 insertions, 39 deletions
diff --git a/src/client/views/collections/CollectionCarouselView.scss b/src/client/views/collections/CollectionCarouselView.scss
index c4679e888..b402a7a32 100644
--- a/src/client/views/collections/CollectionCarouselView.scss
+++ b/src/client/views/collections/CollectionCarouselView.scss
@@ -27,10 +27,10 @@
.carouselView-fwd,
.carouselView-star,
.carouselView-remove,
-.carouselView-check {
+.carouselView-check,
+.carouselView-add {
position: absolute;
display: flex;
- top: 42.5%;
width: 30;
height: 30;
align-items: center;
@@ -43,15 +43,22 @@
}
}
.carouselView-fwd {
+ top: 42.5%;
right: 20;
}
.carouselView-back {
+ top: 42.5%;
left: 20;
}
.carouselView-star {
top: 0;
left: 0;
}
+.carouselView-add {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+}
.carouselView-remove {
top: 80%;
left: 52%;
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index 9cf7765dd..b5b6e1f4b 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -4,6 +4,7 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
+import { Docs } from '../../documents/Documents';
import * as React from 'react';
import { StopEvent, returnFalse, returnOne, returnTrue, returnZero } from '../../../ClientUtils';
import { emptyFunction } from '../../../Utils';
@@ -48,7 +49,8 @@ export class CollectionCarouselView extends CollectionSubView() {
constructor(props: any) {
super(props);
makeObservable(this);
- this.layoutDoc.filterOp = cardMode.ALL;
+ // this.layoutDoc.filterOp = cardMode.ALL;
+ Doc.setDocFilter(this.Document, 'data_star', undefined, 'match');
this.layoutDoc.practiceMode = practiceMode.NORMAL;
this.layoutDoc._carousel_index = 0;
}
@@ -177,9 +179,12 @@ export class CollectionCarouselView extends CollectionSubView() {
this.layoutDoc.filterOp = mode;
switch (mode) {
case cardMode.STAR:
+ Doc.setDocFilter(this.Document, 'data_star', true, 'match');
this.move(1);
break;
- default: this.setFilterMessage(undefined); // prettier-ignore
+ default:
+ this.setFilterMessage(undefined); // prettier-ignore
+ Doc.setDocFilter(this.Document, 'data_star', true, 'remove');
}
};
@@ -197,6 +202,7 @@ export class CollectionCarouselView extends CollectionSubView() {
NativeHeight={returnZero}
fitWidth={undefined}
setContentViewBox={undefined}
+ childFilters={this.childDocFilters}
onDoubleClickScript={this.onContentDoubleClick}
onClickScript={this.onContentClick}
isDocumentActive={this._props.childDocumentsActive?.() ? this._props.isDocumentActive : this._props.isContentActive}
@@ -227,6 +233,16 @@ export class CollectionCarouselView extends CollectionSubView() {
</>
);
}
+
+ containsDifTypes = (): boolean => {
+ return this.carouselItems.filter(doc => !doc.layout.isFlashcard).length === 0;
+ };
+
+ addFlashcard() {
+ const newDoc = Docs.Create.ComparisonDocument('', { _layout_isFlashcard: true, _width: 300, _height: 300 });
+ this.addDocument?.(newDoc);
+ }
+
@computed get buttons() {
if (!this.carouselItems?.[NumCast(this.layoutDoc._carousel_index)]) return null;
return (
@@ -237,17 +253,32 @@ export class CollectionCarouselView extends CollectionSubView() {
<div key="fwd" className="carouselView-fwd" onClick={this.advance}>
<FontAwesomeIcon icon="chevron-right" size="2x" />
</div>
- <div key="star" className="carouselView-star" onClick={this.star}>
- <FontAwesomeIcon icon="star" color={this.carouselItems?.[NumCast(this.layoutDoc._carousel_index)].layout[this.starField] ? 'yellow' : 'gray'} size="1x" />
- </div>
+ {!this.containsDifTypes() ? (
+ <div>
+ <Tooltip title="star">
+ <div key="star" className="carouselView-star" onClick={this.star}>
+ <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">
+ <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>
+ </div>
+ ) : null}
{this.layoutDoc.practiceMode === practiceMode.PRACTICE ? (
<div>
- <div key="remove" className="carouselView-remove" onClick={e => this.setPracticeVal(e, practiceVal.MISSED)}>
- <FontAwesomeIcon icon="xmark" color="red" size="1x" />
- </div>
- <div key="check" className="carouselView-check" onClick={e => this.setPracticeVal(e, practiceVal.CORRECT)}>
- <FontAwesomeIcon icon="check" color="green" size="1x" />
- </div>
+ <Tooltip title="Incorrect. View again later.">
+ <div key="remove" className="carouselView-remove" onClick={e => this.setPracticeVal(e, practiceVal.MISSED)}>
+ <FontAwesomeIcon icon="xmark" color="red" size="1x" />
+ </div>
+ </Tooltip>
+ <Tooltip title="Correct">
+ <div key="check" className="carouselView-check" onClick={e => this.setPracticeVal(e, practiceVal.CORRECT)}>
+ <FontAwesomeIcon icon="check" color="green" size="1x" />
+ </div>
+ </Tooltip>
</div>
) : null}
</>
@@ -320,7 +351,7 @@ export class CollectionCarouselView extends CollectionSubView() {
}}>
Recently missed!
</p>
- {this.menu}
+ {!this.containsDifTypes() ? 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 dc107b576..0b2c356e5 100644
--- a/src/client/views/nodes/ComparisonBox.scss
+++ b/src/client/views/nodes/ComparisonBox.scss
@@ -14,9 +14,8 @@
-webkit-text-stroke-color: black;
-webkit-text-stroke-width: 0.2px;
}
-
.input-box {
- position: relative;
+ position: absolute;
padding: 10px;
width: 100%;
height: 100%;
@@ -145,6 +144,15 @@
}
}
+.explain {
+ position: absolute;
+ top: 10px;
+ left: 10px;
+ z-index: 200;
+ padding: 5px;
+ background: #dfdfdf;
+}
+
.comparisonBox-interactive {
pointer-events: unset;
cursor: ew-resize;
@@ -154,6 +162,7 @@
display: flex;
}
}
+
// .input-box {
// position: absolute;
// padding: 10px;
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx
index 02ab76c2a..9eb5f6ca2 100644
--- a/src/client/views/nodes/ComparisonBox.tsx
+++ b/src/client/views/nodes/ComparisonBox.tsx
@@ -43,9 +43,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
@observable private _inputValue = '';
@observable private _outputValue = '';
@observable private _loading = false;
- @observable private _errorMessage = '';
- @observable private _outputMessage = '';
@observable private _isEmpty = false;
+ @observable _yRelativeToTop: boolean = true;
public addToCollection: ((doc: Doc | Doc[], annotationKey?: string | undefined) => boolean) | undefined;
@@ -76,8 +75,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
componentDidMount() {
this._props.setContentViewBox?.(this);
reaction(
- () => this._props.isSelected(),
- selected => !selected && (this.childActive = false)
+ () => 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) => {
@@ -283,8 +282,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
})
}
style={{
- background: usepath === 'alternate' ? 'white' : 'black',
- color: usepath === 'alternate' ? 'black' : 'white',
+ background: this.revealOp === 'hover' ? 'gray' : usepath === 'alternate' ? 'white' : 'black',
+ color: this.revealOp === 'hover' ? 'black' : usepath === 'alternate' ? 'black' : 'white',
display: 'inline-block',
}}>
<div key="alternate" className="formattedTextBox-flip">
@@ -303,7 +302,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
this.layoutDoc[`_${this._props.fieldKey}_usePath`] === 'alternate' ? (
<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</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: '56px', cursor: 'pointer' }} onPointerDown={e => (!this.layoutDoc[`_${this._props.fieldKey}_usePath`] ? this.askGPT(GPTCallType.CHATCARD) : null)}>
@@ -314,16 +313,17 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
<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),
- _height: NumCast(this.layoutDoc['_' + this._props.fieldKey + '_width'], 200),
+ _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'] = e.clientX - 820;
- newCol['y'] = e.clientY - 640;
+ 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;
@@ -332,9 +332,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
</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.revealOp === 'hover' ? (this.layoutDoc[`_${this._props.fieldKey}_revealOp`] = 'flip') : (this.layoutDoc[`_${this._props.fieldKey}_revealOp`] = 'hover'))}>
+ <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" />
</div>
</Tooltip>
@@ -361,6 +359,17 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
if (this._inputValue) this.askGPT(GPTCallType.QUIZ);
};
+ @action handleHover = () => {
+ if (this.revealOp === 'hover') {
+ this.layoutDoc[`_${this._props.fieldKey}_revealOp`] = 'flip';
+ this.Document.forceActive = false;
+ } else {
+ this.layoutDoc[`_${this._props.fieldKey}_revealOp`] = 'hover';
+ this.Document.forceActive = true;
+ }
+ //this.revealOp === 'hover' ? (this.layoutDoc[`_${this._props.fieldKey}_revealOp`] = 'flip') : (this.layoutDoc[`_${this._props.fieldKey}_revealOp`] = 'hover');
+ };
+
@action handleRenderClick = () => {
// Call the GPT model and get the output
this.layoutDoc[`_${this._props.fieldKey}_usePath`] = undefined;
@@ -448,6 +457,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 ? (
<>
@@ -500,20 +510,32 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
// add text box to each side when comparison box is first created
// (!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 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._isEmpty) {
- const dataSplit = StrCast(this.dataDoc.data).split('Answer');
+ 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
@@ -552,6 +574,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
);
}
+ console.log('HEREEE2' + StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text));
// render a normal flashcard when not a QuizCard
return (
<div
@@ -566,6 +589,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}
{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 2f6824466..cedd3c7c3 100644
--- a/src/client/views/pdf/AnchorMenu.tsx
+++ b/src/client/views/pdf/AnchorMenu.tsx
@@ -24,6 +24,8 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
private _disposer: IReactionDisposer | undefined;
private _commentRef = React.createRef<HTMLDivElement>();
private _cropRef = React.createRef<HTMLDivElement>();
+ // @observable protected _top: number = -300;
+ // @observable protected _left: number = -300;
constructor(props: any) {
super(props);
@@ -38,10 +40,17 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
// GPT additions
@observable private _selectedText: string = '';
+ @observable private _x: number = 0;
+ @observable private _y: number = 0;
@action
public setSelectedText = (txt: string) => {
this._selectedText = txt.trim();
};
+ @action
+ public setLocation = (x: number, y: number) => {
+ this._x = x;
+ this._y = y;
+ };
public onMakeAnchor: () => Opt<Doc> = () => undefined; // Method to get anchor from text search
@@ -99,7 +108,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
* Invokes the API with the selected text and stores it in the selected text.
* @param e pointer down event
*/
- gptFlashcards = async () => {
+ gptFlashcards = async (e: React.PointerEvent) => {
const queryText = this._selectedText;
try {
const res = await gptAPICall(queryText, GPTCallType.FLASHCARD);
@@ -117,8 +126,8 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
*/
transferToFlashcard = (text: string) => {
// put each question generated by GPT on the front of the flashcard
- const senArr = text.split('Question');
- const collectionArr: Doc[] = [];
+ var senArr = text.trim().split('Question: ');
+ var collectionArr: Doc[] = [];
for (let i = 1; i < senArr.length; i++) {
console.log('Arr ' + i + ': ' + senArr[i]);
const newDoc = Docs.Create.ComparisonDocument(senArr[i], { _layout_isFlashcard: true, _width: 300, _height: 300 });
@@ -133,6 +142,10 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
_layout_autoHeight: true,
});
+ newCol.x = this._x;
+ newCol.y = this._y;
+ newCol.zIndex = 100;
+
this.addToCollection?.(newCol);
};
@@ -221,7 +234,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
{/* Adds a create flashcards option to the anchor menu, which calls the gptFlashcard method. */}
<IconButton
tooltip="Create flashcards" //
- onPointerDown={this.gptFlashcards}
+ onPointerDown={e => this.gptFlashcards(e)}
icon={<FontAwesomeIcon icon="id-card" size="lg" />}
color={SettingsManager.userColor}
/>
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 6c1617c38..92f890e70 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -425,6 +425,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
const sel = window.getSelection();
if (sel) {
AnchorMenu.Instance.setSelectedText(sel.toString());
+ AnchorMenu.Instance.setLocation(NumCast(this._props.layoutDoc['x']), NumCast(this._props.layoutDoc['y']));
}
if (sel?.type === 'Range') {