aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/.DS_Storebin10244 -> 10244 bytes
-rw-r--r--src/client/apis/gpt/GPT.ts8
-rw-r--r--src/client/documents/Documents.ts4
-rw-r--r--src/client/util/CurrentUserUtils.ts5
-rw-r--r--src/client/views/collections/CollectionCarouselView.scss18
-rw-r--r--src/client/views/collections/CollectionCarouselView.tsx76
-rw-r--r--src/client/views/collections/CollectionView.tsx9
-rw-r--r--src/client/views/nodes/ComparisonBox.tsx181
-rw-r--r--src/client/views/pdf/AnchorMenu.tsx23
-rw-r--r--src/client/views/pdf/GPTPopup/GPTPopup.tsx39
-rw-r--r--src/client/views/pdf/PDFViewer.tsx4
11 files changed, 315 insertions, 52 deletions
diff --git a/src/.DS_Store b/src/.DS_Store
index f8d745dbf..f1f08fbb5 100644
--- a/src/.DS_Store
+++ b/src/.DS_Store
Binary files differ
diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts
index cea862330..968b45273 100644
--- a/src/client/apis/gpt/GPT.ts
+++ b/src/client/apis/gpt/GPT.ts
@@ -4,6 +4,7 @@ enum GPTCallType {
SUMMARY = 'summary',
COMPLETION = 'completion',
EDIT = 'edit',
+ FLASHCARD = 'flashcard',
}
type GPTCallOpts = {
@@ -14,9 +15,10 @@ type GPTCallOpts = {
};
const callTypeMap: { [type: string]: GPTCallOpts } = {
- summary: { model: 'text-davinci-003', maxTokens: 256, temp: 0.5, prompt: 'Summarize this text in simpler terms: ' },
- edit: { model: 'text-davinci-003', maxTokens: 256, temp: 0.5, prompt: 'Reword this: ' },
- completion: { model: 'text-davinci-003', maxTokens: 256, temp: 0.5, prompt: '' },
+ summary: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: 'Summarize this text in simpler terms: ' },
+ edit: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: 'Reword this: ' },
+ flashcard: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: 'Make flashcards out of this text with questions on the front and answers on the back: ' },
+ completion: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: '' },
};
/**
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 2d2d13519..bf3d14560 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -1054,8 +1054,8 @@ export namespace Docs {
return InstanceFromProto(Prototypes.get(DocumentType.SCREENSHOT), '', options);
}
- export function ComparisonDocument(options: DocumentOptions = { title: 'Comparison Box' }) {
- return InstanceFromProto(Prototypes.get(DocumentType.COMPARISON), undefined, options);
+ export function ComparisonDocument(text: string, options: DocumentOptions = { title: 'Comparison Box' }) {
+ return InstanceFromProto(Prototypes.get(DocumentType.COMPARISON), text, options);
}
export function AudioDocument(url: string, options: DocumentOptions = {}, overwriteDoc?: Doc) {
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 958240f94..ab0315ba1 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -341,14 +341,15 @@ pie title Minerals in my tap water
creator:(opts:DocumentOptions)=> any // how to create the empty thing if it doesn't exist
}[] = [
{key: "Note", creator: opts => Docs.Create.TextDocument("", opts), opts: { _width: 200, _layout_autoHeight: true }},
- {key: "Flashcard", creator: Docs.Create.ComparisonDocument, opts: { _layout_isFlashcard: true, _width: 300, _height: 300 }},
+ {key: "Flashcard", creator: opts => Docs.Create.ComparisonDocument("", opts), opts: { _layout_isFlashcard: true, _width: 300, _height: 300}},
+ // {key: "Flashcard", creator: Docs.Create.ComparisonDocument("", opts), opts: { _layout_isFlashcard: true, _width: 300, _height: 300 }},
//{key: "Flashcard", creator: opts => Docs.Create.TextDocument("", opts), opts: { _width: 200, _layout_autoHeight: true, _layout_enableAltContentUI: true}},
{key: "Equation", creator: opts => Docs.Create.EquationDocument("",opts), opts: { _width: 300, _height: 35, }},
{key: "Noteboard", creator: opts => Docs.Create.NoteTakingDocument([], opts), opts: { _width: 250, _height: 200, _layout_fitWidth: true}},
{key: "Simulation", creator: opts => Docs.Create.SimulationDocument(opts), opts: { _width: 300, _height: 300, }},
{key: "Collection", creator: opts => Docs.Create.FreeformDocument([], opts), opts: { _width: 150, _height: 100, _layout_fitWidth: true }},
{key: "Webpage", creator: opts => Docs.Create.WebDocument("",opts), opts: { _width: 400, _height: 512, _nativeWidth: 850, data_useCors: true, }},
- {key: "Comparison", creator: Docs.Create.ComparisonDocument, opts: { _width: 300, _height: 300 }},
+ {key: "Comparison", creator: opts => Docs.Create.ComparisonDocument("",opts), opts: { _width: 300, _height: 300 }},
{key: "Audio", creator: opts => Docs.Create.AudioDocument(nullAudio, opts),opts: { _width: 200, _height: 100, }},
{key: "Map", creator: opts => Docs.Create.MapDocument([], opts), opts: { _width: 800, _height: 600, _layout_fitWidth: true, }},
{key: "Screengrab", creator: Docs.Create.ScreenshotDocument, opts: { _width: 400, _height: 200 }},
diff --git a/src/client/views/collections/CollectionCarouselView.scss b/src/client/views/collections/CollectionCarouselView.scss
index 130b31325..f115bb40a 100644
--- a/src/client/views/collections/CollectionCarouselView.scss
+++ b/src/client/views/collections/CollectionCarouselView.scss
@@ -13,7 +13,10 @@
}
}
.carouselView-back,
-.carouselView-fwd {
+.carouselView-fwd,
+.carouselView-star,
+.carouselView-remove,
+.carouselView-check {
position: absolute;
display: flex;
top: 42.5%;
@@ -34,6 +37,19 @@
.carouselView-back {
left: 20;
}
+.carouselView-star {
+ top: 0;
+ right: 20;
+}
+.carouselView-remove {
+ top: 80%;
+ left: 52%;
+}
+.carouselView-check {
+ top: 80%;
+ right: 52%;
+}
+
.carouselView-back:hover,
.carouselView-fwd:hover {
background: lightgray;
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index dae16bafb..7f5176123 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -36,11 +36,67 @@ export class CollectionCarouselView extends CollectionSubView() {
advance = (e: React.MouseEvent) => {
e.stopPropagation();
this.layoutDoc._carousel_index = (NumCast(this.layoutDoc._carousel_index) + 1) % this.childLayoutPairs.length;
+ var startInd = this.layoutDoc._carousel_index;
+
+ // if the star filter is selected
+ if (this.layoutDoc[`_${this._props.fieldKey}_filterOp`] == 'star') {
+ // go to a new index that is starred, skip the ones that aren't
+ while (!this.childLayoutPairs?.[NumCast(startInd)].layout[`${this.fieldKey}_star`] && (startInd + 1) % this.childLayoutPairs.length != this.layoutDoc._carousel_index) {
+ startInd = (startInd + 1) % this.childLayoutPairs.length;
+ }
+ this.layoutDoc._carousel_index = startInd;
+ }
+
+ // if the practice filter is selected
+ if (this.layoutDoc[`_${this._props.fieldKey}_filterOp`] == 'practice') {
+ // go to a new index that is missed, skip the ones that are correct
+ while (this.childLayoutPairs?.[NumCast(startInd)].layout[`${this.fieldKey}_missed`] == 'correct' && (startInd + 1) % this.childLayoutPairs.length != this.layoutDoc._carousel_index) {
+ startInd = (startInd + 1) % this.childLayoutPairs.length;
+ }
+ this.layoutDoc._carousel_index = startInd;
+ }
};
goback = (e: React.MouseEvent) => {
e.stopPropagation();
this.layoutDoc._carousel_index = (NumCast(this.layoutDoc._carousel_index) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
+
+ var startInd = this.layoutDoc._carousel_index;
+
+ // if the star filter is selected
+ if (this.layoutDoc[`_${this._props.fieldKey}_filterOp`] == 'star') {
+ // go to a new index that is starred, skip the ones that aren't
+ while (!this.childLayoutPairs?.[NumCast(startInd)].layout[`${this.fieldKey}_star`] && (startInd - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length != this.layoutDoc._carousel_index) {
+ startInd = (startInd - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
+ }
+ this.layoutDoc._carousel_index = startInd;
+ }
+
+ // if the practice filter is selected
+ if (this.layoutDoc[`_${this._props.fieldKey}_filterOp`] == 'practice') {
+ // go to a new index that is missed, skip the ones that are correct
+ while (this.childLayoutPairs?.[NumCast(startInd)].layout[`${this.fieldKey}_missed`] == 'correct' && (startInd - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length != this.layoutDoc._carousel_index) {
+ startInd = (startInd - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
+ }
+ this.layoutDoc._carousel_index = startInd;
+ }
+ };
+
+ star = (e: React.MouseEvent) => {
+ e.stopPropagation();
+ // stars the document when the button is pressed
+ const curDoc = this.childLayoutPairs?.[NumCast(this.layoutDoc._carousel_index)];
+ if (curDoc.layout[`${this.fieldKey}_star`] == undefined) curDoc.layout[`${this.fieldKey}_star`] = true;
+ else curDoc.layout[`${this.fieldKey}_star`] = !curDoc.layout[`${this.fieldKey}_star`];
+ };
+
+ missed = (e: React.MouseEvent, val: string) => {
+ e.stopPropagation();
+ const curDoc = this.childLayoutPairs?.[NumCast(this.layoutDoc._carousel_index)];
+ curDoc.layout[`${this.fieldKey}_missed`] = val;
+ this.layoutDoc._carousel_index = (NumCast(this.layoutDoc._carousel_index) + 1) % this.childLayoutPairs.length;
+ this.advance;
};
+
captionStyleProvider = (doc: Doc | undefined, captionProps: Opt<FieldViewProps>, property: string): any => {
// first look for properties on the document in the carousel, then fallback to properties on the container
const childValue = doc?.['caption-' + property] ? this._props.styleProvider?.(doc, captionProps, property) : undefined;
@@ -106,6 +162,15 @@ 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.childLayoutPairs?.[NumCast(this.layoutDoc._carousel_index)].layout[`${this.fieldKey}_star`] ? 'yellow' : 'gray'} size={'1x'} />
+ </div>
+ <div key="remove" className="carouselView-remove" onClick={e => this.missed(e, 'missed')} style={{ visibility: this.layoutDoc[`_${this._props.fieldKey}_filterOp`] == 'practice' ? 'visible' : 'hidden' }}>
+ <FontAwesomeIcon icon={'xmark'} color={'red'} size={'1x'} />
+ </div>
+ <div key="check" className="carouselView-check" onClick={e => this.missed(e, 'correct')} style={{ visibility: this.layoutDoc[`_${this._props.fieldKey}_filterOp`] == 'practice' ? 'visible' : 'hidden' }}>
+ <FontAwesomeIcon icon={'check'} color={'green'} size={'1x'} />
+ </div>
</>
);
}
@@ -120,6 +185,17 @@ export class CollectionCarouselView extends CollectionSubView() {
color: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color),
}}>
{this.content}
+ <p
+ style={{
+ color: 'red',
+ zIndex: '999',
+ position: 'relative',
+ left: '10px',
+ top: '10px',
+ visibility: this.childLayoutPairs?.[NumCast(this.layoutDoc._carousel_index)].layout[`${this.fieldKey}_missed`] == 'missed' ? 'visible' : 'hidden',
+ }}>
+ Recently missed!
+ </p>
{this.Document._chromeHidden ? null : this.buttons}
</div>
);
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 18eb4dd1f..168176edf 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -176,6 +176,15 @@ export class CollectionView extends ViewBoxAnnotatableComponent<CollectionViewPr
return newRendition;
});
+ const revealOptions = cm.findByDescription('Filter Flashcards');
+ const revealItems: ContextMenuProps[] = revealOptions && 'subitems' in revealOptions ? revealOptions.subitems : [];
+ revealItems.push({ description: 'All', event: () => (this.layoutDoc[`_${this._props.fieldKey}_filterOp`] = 'all'), icon: 'eye-slash' });
+ revealItems.push({ description: 'Star', event: () => (this.layoutDoc[`_${this._props.fieldKey}_filterOp`] = 'star'), icon: 'hand-point-up' });
+ revealItems.push({ description: 'Practice Mode', event: () => (this.layoutDoc[`_${this._props.fieldKey}_filterOp`] = 'practice'), icon: 'rotate' });
+
+ //revealItems.push({ description: 'Bring to Front', event: () => SelectionManager.Views.forEach(dv => dv._props.bringToFront?.(dv.Document, false)), icon: 'arrow-up' });
+ !revealOptions && cm.addItem({ description: 'Filter Flashcards', addDivider: false, noexpand: true, subitems: revealItems, icon: 'layer-group' });
+
const options = cm.findByDescription('Options...');
const optionItems = options && 'subitems' in options ? options.subitems : [];
!Doc.noviceMode ? optionItems.splice(0, 0, { description: `${this.Document.forceActive ? 'Select' : 'Force'} Contents Active`, event: () => (this.Document.forceActive = !this.Document.forceActive), icon: 'project-diagram' }) : null;
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx
index 81f624b20..ce862cd22 100644
--- a/src/client/views/nodes/ComparisonBox.tsx
+++ b/src/client/views/nodes/ComparisonBox.tsx
@@ -4,13 +4,14 @@ import { observer } from 'mobx-react';
import * as React from 'react';
import { emptyFunction, returnFalse, returnNone, returnZero, setupMoveUpEvents } from '../../../Utils';
import { Doc, Opt } from '../../../fields/Doc';
-import { DocCast, NumCast, StrCast } from '../../../fields/Types';
+import { DocCast, NumCast, RTFCast, StrCast } from '../../../fields/Types';
import { DocUtils, Docs } from '../../documents/Documents';
import { DragManager, dropActionType } from '../../util/DragManager';
import { undoBatch } from '../../util/UndoManager';
import { SnappingManager } from '../../util/SnappingManager';
import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent';
import { StyleProp } from '../StyleProvider';
+import { Tooltip } from '@mui/material';
import { CSSTransition } from 'react-transition-group';
import './ComparisonBox.scss';
import { DocumentView } from './DocumentView';
@@ -18,6 +19,8 @@ import { FieldView, FieldViewProps } from './FieldView';
import { PinProps, PresBox } from './trails';
import { FormattedTextBox } from './formattedText/FormattedTextBox';
import { RichTextField } from '../../../fields/RichTextField';
+import { GPTCallType, gptAPICall } from '../../apis/gpt/GPT';
+import { DocData } from '../../../fields/DocSymbols';
@observer
export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implements ViewBoxInterface {
@@ -88,7 +91,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
if (this._isAnyChildContentActive) return;
this._animating = 'all 200ms';
// on click, animate slider movement to the targetWidth
- this.layoutDoc[this.clipWidthKey] = (targetWidth * 100) / this._props.PanelWidth();
+ // this.layoutDoc[this.clipWidthKey] = (targetWidth * 100) / this._props.PanelWidth();
+ this.layoutDoc[this.clipHeightKey] = (targetWidth * 100) / this._props.PanelHeight();
setTimeout(
action(() => (this._animating = '')),
@@ -128,7 +132,6 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
clearDoc = (fieldKey: string) => {
delete this.dataDoc[fieldKey];
this.dataDoc[fieldKey] = 'empty';
- // this.dataDoc[this.fieldKey + '_1'] = 'empty';
};
// clearDoc = (fieldKey: string) => delete this.dataDoc[fieldKey];
@@ -182,47 +185,72 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
this.layoutDoc[`_${this._props.fieldKey}_usePath`] = usePath === undefined ? 'alternate' : undefined;
};
+ hoverFlip = (side: string | undefined) => {
+ if (this.layoutDoc[`_${this._props.fieldKey}_revealOp`] == 'hover') this.layoutDoc[`_${this._props.fieldKey}_usePath`] = side;
+ };
@computed get overlayAlternateIcon() {
const usepath = this.layoutDoc[`_${this._props.fieldKey}_usePath`];
return (
- <div
- className="formattedTextBox-alternateButton"
- onPointerDown={e =>
- setupMoveUpEvents(e.target, e, returnFalse, emptyFunction, e => {
- console.log(this.layoutDoc[`_${this._props.fieldKey}_revealOp`]);
- if (!this.layoutDoc[`_${this._props.fieldKey}_revealOp`] || this.layoutDoc[`_${this._props.fieldKey}_revealOp`] == 'flip') {
- this.flipFlashcard();
- }
- })
- }
- style={{
- //display: this._props.isContentActive() && !SnappingManager.IsDragging ? 'flex' : 'none',
- background: usepath === 'alternate' ? 'white' : 'black',
- color: usepath === 'alternate' ? 'black' : 'white',
- }}>
- <FontAwesomeIcon icon="turn-up" size="sm" />
- </div>
+ <Tooltip title={<div className="dash-tooltip">flip</div>}>
+ <div
+ className="formattedTextBox-alternateButton"
+ onPointerDown={e =>
+ setupMoveUpEvents(e.target, e, returnFalse, emptyFunction, e => {
+ console.log(this.layoutDoc[`_${this._props.fieldKey}_revealOp`]);
+ if (!this.layoutDoc[`_${this._props.fieldKey}_revealOp`] || this.layoutDoc[`_${this._props.fieldKey}_revealOp`] == 'flip') {
+ this.flipFlashcard();
+ }
+ })
+ }
+ style={{
+ //display: this._props.isContentActive() && !SnappingManager.IsDragging ? 'flex' : 'none',
+ background: usepath === 'alternate' ? 'white' : 'black',
+ color: usepath === 'alternate' ? 'black' : 'white',
+ }}>
+ <FontAwesomeIcon icon="turn-up" size="sm" />
+ </div>
+ </Tooltip>
);
}
render() {
const clearButton = (which: string) => {
return (
- <div
- 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" />
- </div>
+ <Tooltip title={<div className="dash-tooltip">remove</div>}>
+ <div
+ 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" />
+ </div>
+ </Tooltip>
);
};
const displayDoc = (which: string) => {
const whichDoc = DocCast(this.dataDoc[which]);
const targetDoc = DocCast(whichDoc?.annotationOn, whichDoc);
// if there is no Doc in the first comparison slot, but the comparison box's fieldKey slot has a RichTextField, then render a text box to show the contents of the document's field key slot
- const layoutTemplateString = !targetDoc && which.endsWith('1') && this.Document[this.fieldKey] instanceof RichTextField ? FormattedTextBox.LayoutString(this.fieldKey) : undefined;
+ //const layoutTemplateString = !targetDoc && which.endsWith('1') && this.Document[this.fieldKey] instanceof RichTextField ? FormattedTextBox.LayoutString(this.fieldKey) : undefined;
+ const subjectText = RTFCast(this.Document[this.fieldKey])?.Text;
+ const layoutTemplateString = !targetDoc
+ ? which.endsWith('0') && subjectText !== undefined
+ ? FormattedTextBox.LayoutString(this.fieldKey)
+ : which.endsWith('1') && (this.Document[which] instanceof RichTextField || typeof this.Document[which] === 'string')
+ ? FormattedTextBox.LayoutString(which)
+ : undefined
+ : undefined;
+
+ if (which.endsWith('1') && !layoutTemplateString && targetDoc) {
+ const queryText = RTFCast(this.Document[this.fieldKey + '_1'])?.Text;
+ console.log('QUER' + queryText);
+ if (queryText?.includes('--TEXT--') && subjectText) {
+ this.Document[DocData][this.fieldKey + '_1'] = '';
+ gptAPICall(queryText?.replace('--TEXT--', subjectText), GPTCallType.COMPLETION).then(value => (this.Document[DocData][this.fieldKey + '_1'] = value.trim()));
+ }
+ }
+
return targetDoc || layoutTemplateString ? (
<>
<DocumentView
@@ -234,7 +262,9 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
moveDocument={which.endsWith('1') ? this.moveDoc1 : this.moveDoc2}
removeDocument={which.endsWith('1') ? this.remDoc1 : this.remDoc2}
NativeWidth={() => NumCast(this.layoutDoc.width, 200)}
- NativeHeight={() => NumCast(this.layoutDoc.height, 200)}
+ NativeHeight={(): number => {
+ return NumCast(this.layoutDoc.height, 200);
+ }}
isContentActive={emptyFunction}
isDocumentActive={returnFalse}
whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
@@ -251,6 +281,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
);
};
const displayBox = (which: string, index: number, cover: number) => {
+ // if (this.layoutDoc[`_${this._props.fieldKey}_revealOp`] == 'hide/reveal') this.layoutDoc[this.clipHeightKey] = 100;
+ // else this.layoutDoc.height = 300;
return (
<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)}
@@ -258,26 +290,89 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
);
};
+ const displayBoxReveal = (which: string, which2: string, index: number, cover: number) => {
+ return (
+ <div style={{ display: 'flex', flexDirection: 'column' }}>
+ <div
+ className={`beforeBox-cont`}
+ key={which}
+ style={{ width: this._props.PanelWidth(), height: NumCast(this.layoutDoc.height, 200) / 2 }}
+ onPointerDown={e => this.registerSliding(e, cover)}
+ ref={ele => this.createDropTarget(ele, which, 0)}>
+ {displayDoc(which)}
+ </div>
+ <div
+ className={`afterBox-cont`}
+ key={which2}
+ style={{ width: this._props.PanelWidth(), height: NumCast(this.layoutDoc.height, 200) / 2 }}
+ onPointerDown={e => this.registerSliding(e, cover)}
+ ref={ele => this.createDropTarget(ele, which2, 1)}>
+ {displayDoc(which2)}
+ </div>
+ </div>
+ );
+ };
+
if (this.Document._layout_isFlashcard) {
const side = this.layoutDoc[`_${this._props.fieldKey}_usePath`] === 'alternate' ? 1 : 0;
- if (!(this.dataDoc[this.fieldKey + '_0'] || this.dataDoc[this.fieldKey + '_0'] == 'empty')) this.dataDoc[this.fieldKey + '_0'] = DocUtils.copyDragFactory(Doc.UserDoc().emptyNote as Doc);
+ // add text box when first created
+ if (!(this.dataDoc[this.fieldKey + '_0'] || this.dataDoc[this.fieldKey + '_0'] == 'empty')) {
+ console.log('TEXT HERE' + this.dataDoc.data);
+ const newDoc = Docs.Create.TextDocument(StrCast(this.dataDoc.data));
+ this.addDoc(newDoc, this.fieldKey + '_0');
+ }
+ // if (!(this.dataDoc[this.fieldKey + '_0'] || this.dataDoc[this.fieldKey + '_0'] == 'empty')) this.dataDoc[this.fieldKey + '_0'] = DocUtils.copyDragFactory(Doc.UserDoc().emptyNote as Doc);
if (!(this.dataDoc[this.fieldKey + '_1'] || this.dataDoc[this.fieldKey + '_1'] == 'empty')) this.dataDoc[this.fieldKey + '_1'] = DocUtils.copyDragFactory(Doc.UserDoc().emptyNote as Doc);
- return (
- <div
- className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}`} /* change className to easily disable/enable pointer events in CSS */
- onMouseEnter={() => {
- if (this.layoutDoc[`_${this._props.fieldKey}_revealOp`] == 'hover') this.layoutDoc[`_${this._props.fieldKey}_usePath`] = 'alternate';
- }}
- onMouseLeave={() => {
- if (this.layoutDoc[`_${this._props.fieldKey}_revealOp`] == 'hover') this.layoutDoc[`_${this._props.fieldKey}_usePath`] = undefined;
- }}>
- {displayBox(`${this.fieldKey}_${side}`, side, this._props.PanelWidth() - 3)}
+ if (this.layoutDoc[`_${this._props.fieldKey}_revealOp`] == 'hide/reveal') {
+ {
+ return (
+ <div className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}`} style={{ display: 'flex', flexDirection: 'column' }}>
+ {displayBox(`${this.fieldKey}_0`, side, this._props.PanelHeight() - 3)}
+ {displayBox(`${this.fieldKey}_1`, 1, this._props.PanelHeight() - 3)}
+ </div>
+ );
+ // return (
+ // <div className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}` /* change className to easily disable/enable pointer events in CSS */} style={{ display: 'flex', flexDirection: 'column' }}>
+ // {displayBox(`${this.fieldKey}_2`, 1, this._props.PanelHeight() - 3)}
+ // <div className="clip-div" style={{ height: this.clipHeight + '%', transition: this._animating, background: StrCast(this.layoutDoc._backgroundColor, 'gray') }}>
+ // {displayBox(`${this.fieldKey}_1`, 0, 0)}
+ // </div>
+ // </div>
+ // );
+ // return (
+ // <div className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}` /* change className to easily disable/enable pointer events in CSS */}>
+ // {displayBox(`${this.fieldKey}_${side === 0 ? 1 : 0}`, side, this._props.PanelHeight() / 2)}
+ // {displayBox(`${this.fieldKey}_${side === 0 ? 0 : 1}`, 1, this._props.PanelHeight() / 2)}
- {this.overlayAlternateIcon}
- </div>
- );
+ // </div>
+ // );
+ }
+ } else {
+ return (
+ <div
+ className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}`} /* change className to easily disable/enable pointer events in CSS */
+ // style={{ display: 'flex', flexDirection: 'column' }}
+ // style={{ position: 'absolute', top: '0px' }}
+ onMouseEnter={() => {
+ this.hoverFlip('alternate');
+ }}
+ onMouseLeave={() => {
+ this.hoverFlip(undefined);
+ }}>
+ {displayBox(`${this.fieldKey}_${side === 0 ? 1 : 0}`, side, this._props.PanelWidth() - 3)}
+ {/* {displayBoxReveal(`${this.fieldKey}_${side}`, side, this._props.PanelWidth() - 3)}
+ {displayBoxReveal(`${this.fieldKey}_${side === 0 ? 1 : 0}`, side === 0 ? 1 : 0, this._props.PanelWidth() - 3)} */}
+ {/* <div>{displayBoxReveal(`${this.fieldKey}_${side}`, side, this._props.PanelWidth() - 3)}</div> */}
+ {/* <div style={{ display: this.layoutDoc[`_${this._props.fieldKey}_revealOp`] == 'hide/reveal' ? 'block' : 'none' }} className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}`}>
+ {displayBox(`${this.fieldKey}_${side === 0 ? 1 : 0}`, side === 0 ? 1 : 0, this._props.PanelWidth() - 3)}
+ </div> */}
+
+ {this.overlayAlternateIcon}
+ </div>
+ );
+ }
} else {
return (
<div className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}` /* change className to easily disable/enable pointer events in CSS */}>
diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx
index d0688c338..844c1e36d 100644
--- a/src/client/views/pdf/AnchorMenu.tsx
+++ b/src/client/views/pdf/AnchorMenu.tsx
@@ -6,6 +6,7 @@ import * as React from 'react';
import { ColorResult } from 'react-color';
import { Utils, returnFalse, setupMoveUpEvents, unimplementedFunction } from '../../../Utils';
import { Doc, Opt } from '../../../fields/Doc';
+import { DocUtils, Docs } from '../../documents/Documents';
import { GPTCallType, gptAPICall } from '../../apis/gpt/GPT';
import { DocumentType } from '../../documents/DocumentTypes';
import { SelectionManager } from '../../util/SelectionManager';
@@ -87,6 +88,22 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
GPTPopup.Instance.setLoading(false);
};
+ gptFlashcards = async (e: React.PointerEvent) => {
+ // move this logic to gptpopup, need to implement generate again
+ // GPTPopup.Instance.setVisible(true);
+ // GPTPopup.Instance.setMode(GPTPopupMode.FLASHCARD);
+ // GPTPopup.Instance.setLoading(true);
+
+ try {
+ const res = await gptAPICall(this.selectedText, GPTCallType.FLASHCARD);
+ GPTPopup.Instance.setText(res || 'Something went wrong.');
+ GPTPopup.Instance.transferToFlashcard();
+ } catch (err) {
+ console.error(err);
+ }
+ GPTPopup.Instance.setLoading(false);
+ };
+
pointerDown = (e: React.PointerEvent) => {
setupMoveUpEvents(
this,
@@ -176,6 +193,12 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
color={SettingsManager.userColor}
/>
)}
+ <IconButton
+ tooltip="Create flashcards" //
+ onPointerDown={this.gptFlashcards}
+ icon={<FontAwesomeIcon icon="id-card" size="lg" />}
+ color={SettingsManager.userColor}
+ />
{AnchorMenu.Instance.OnAudio === unimplementedFunction ? null : (
<IconButton
tooltip="Click to Record Annotation" //
diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
index da8a88803..dbcdd4e3a 100644
--- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx
+++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
@@ -15,11 +15,14 @@ import { DocUtils, Docs } from '../../../documents/Documents';
import { ObservableReactComponent } from '../../ObservableReactComponent';
import { AnchorMenu } from '../AnchorMenu';
import './GPTPopup.scss';
+import { ComparisonBox } from '../../nodes/ComparisonBox';
+import { DashColor, emptyFunction, lightOrDark, returnFalse } from '../../../../Utils';
export enum GPTPopupMode {
SUMMARY,
EDIT,
IMAGE,
+ FLASHCARD,
}
interface GPTPopupProps {}
@@ -149,6 +152,22 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
}
};
+ transferToFlashcard = () => {
+ const senArr = this.text.split('.');
+ for (var i = 0; i < senArr.length; i += 2) {
+ console.log('SEN: ' + senArr[i]);
+ const newDoc = Docs.Create.ComparisonDocument(senArr[i], { _layout_isFlashcard: true, _width: 300, _height: 300 });
+ newDoc.text = senArr[i];
+ this.addDoc(newDoc, this.sidebarId);
+ const anchor = AnchorMenu.Instance?.GetAnchor(undefined, false);
+ if (anchor) {
+ DocUtils.MakeLink(newDoc, anchor, {
+ link_relationship: 'GPT Summary',
+ });
+ }
+ }
+ };
+
/**
* Transfers the image urls to actual image docs
*/
@@ -213,6 +232,23 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
);
};
+ flashcardBox = () => {
+ // const textArr = this.text.split(".");
+ // textArr.forEach(function(sentence) {
+ // console.log(sentence);
+
+ // });
+ // const newDoc = Docs.Create.ComparisonDocument();
+ // this.addToCollection?.(newDoc);
+ // // const newDoc = Docs.Create.ComparisonDocument();
+ // DocUtils.copyDragFactory(Doc.UserDoc().emptyFlashcard as Doc);
+ // // this.addToCollection?.(newDoc);
+ // // return newDoc;
+ // <ComparisonBox/>
+ const newDoc = Docs.Create.TextDocument('Hello there');
+ this.addDoc?.(newDoc);
+ };
+
data = () => {
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
@@ -268,6 +304,7 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
<>
<IconButton tooltip="Generate Again" onClick={this.callSummaryApi} icon={<FontAwesomeIcon icon="redo-alt" size="lg" />} color={StrCast(Doc.UserDoc().userVariantColor)} />
<Button tooltip="Transfer to text" text="Transfer To Text" onClick={this.transferToText} color={StrCast(Doc.UserDoc().userVariantColor)} type={Type.TERT} />
+ {/* <Button tooltip="Transfer to flashcard" text="flashcard" onClick={this.transferToFlashcard} color={StrCast(Doc.UserDoc().userVariantColor)} type={Type.TERT} /> */}
</>
) : (
<div className="summarizing">
@@ -308,7 +345,7 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
render() {
return (
<div className="summary-box" style={{ display: this.visible ? 'flex' : 'none' }}>
- {this.mode === GPTPopupMode.SUMMARY ? this.summaryBox() : this.mode === GPTPopupMode.IMAGE ? this.imageBox() : <></>}
+ {this.mode === GPTPopupMode.SUMMARY ? this.summaryBox() : this.mode === GPTPopupMode.IMAGE ? this.imageBox() : this.mode == GPTPopupMode.FLASHCARD ? this.summaryBox() : <></>}
</div>
);
}
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 0d4cfda88..7d8529a1c 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -20,11 +20,13 @@ import { MarqueeAnnotator } from '../MarqueeAnnotator';
import { FocusViewOptions, FieldViewProps } from '../nodes/FieldView';
import { LinkInfo } from '../nodes/LinkDocPreview';
import { PDFBox } from '../nodes/PDFBox';
+import { ComparisonBox } from '../nodes/ComparisonBox';
import { ObservableReactComponent } from '../ObservableReactComponent';
import { StyleProp } from '../StyleProvider';
import { AnchorMenu } from './AnchorMenu';
import { Annotation } from './Annotation';
import { GPTPopup } from './GPTPopup/GPTPopup';
+import { Docs } from '../../documents/Documents';
import './PDFViewer.scss';
const _global = (window /* browser */ || global) /* node */ as any;
@@ -415,6 +417,8 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
// Changing which document to add the annotation to (the currently selected PDF)
GPTPopup.Instance.setSidebarId('data_sidebar');
GPTPopup.Instance.addDoc = this._props.sidebarAddDoc;
+ // const newDoc = Docs.Create.ComparisonDocument({ _layout_isFlashcard: true, _width: 300, _height: 300 });
+ // this.props.addDocument?.(newDoc);
};
@action