diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/MainView.tsx | 1 | ||||
-rw-r--r-- | src/client/views/collections/CollectionCarouselView.scss | 42 | ||||
-rw-r--r-- | src/client/views/collections/CollectionCarouselView.tsx | 53 | ||||
-rw-r--r-- | src/client/views/nodes/ComparisonBox.tsx | 73 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 14 |
5 files changed, 147 insertions, 36 deletions
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 31d88fb87..541b15006 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -548,6 +548,7 @@ export class MainView extends ObservableReactComponent<{}> { fa.faRobot, fa.faSatellite, fa.faStar, + fa.faFilePen, ] ); } diff --git a/src/client/views/collections/CollectionCarouselView.scss b/src/client/views/collections/CollectionCarouselView.scss index 975b352cf..c4679e888 100644 --- a/src/client/views/collections/CollectionCarouselView.scss +++ b/src/client/views/collections/CollectionCarouselView.scss @@ -50,7 +50,7 @@ } .carouselView-star { top: 0; - right: 20; + left: 0; } .carouselView-remove { top: 80%; @@ -60,6 +60,46 @@ top: 80%; right: 52%; } +.carouselView-quiz { + position: absolute; + display: flex; + top: 5px; + right: 8px; + &:hover { + color: white; + } +} + +.carouselView-practice { + position: absolute; + display: flex; + top: 22px; + right: 8px; + &:hover { + color: white; + } +} +.carouselView-starFilter { + position: absolute; + display: flex; + top: 40px; + right: 7px; + &:hover { + color: white; + } +} + +.carouselView-menu { + position: absolute; + display: flex; + top: 2px; + right: 2px; + width: 30; + height: 60; + border-radius: 5px; + color: rgba(255, 255, 255, 0.5); + background: rgba(0, 0, 0, 0.1); +} .carouselView-back:hover, .carouselView-fwd:hover { diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx index 53d14e6e0..8da808065 100644 --- a/src/client/views/collections/CollectionCarouselView.tsx +++ b/src/client/views/collections/CollectionCarouselView.tsx @@ -19,6 +19,7 @@ import { FieldViewProps } from '../nodes/FieldView'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import './CollectionCarouselView.scss'; import { CollectionSubView } from './CollectionSubView'; +import { Tooltip } from '@mui/material'; enum cardMode { PRACTICE = 'practice', @@ -143,22 +144,26 @@ export class CollectionCarouselView extends CollectionSubView() { captionWidth = () => this._props.PanelWidth() - 2 * this.marginX; setFilterMode = (mode: cardMode) => { this.layoutDoc.filterOp = mode; + console.log('MODE' + mode); + console.log('FILT' + this.layoutDoc.filterOp + ';'); if (mode == cardMode.STAR) this.move(1); - if (mode == cardMode.QUIZ) this.carouselItems?.map(doc => (doc.layout[this.sideField] = undefined)); + if (mode == cardMode.QUIZ) { + this.carouselItems?.map(doc => (doc.layout[this.sideField] = undefined)); + } this.carouselItems?.map(doc => (doc.layout[this.practiceField] = undefined)); }; - specificMenu = (): void => { - const cm = ContextMenu.Instance; + // specificMenu = (): void => { + // const cm = ContextMenu.Instance; - const revealOptions = cm.findByDescription('Filter Flashcards'); - const revealItems: ContextMenuProps[] = revealOptions && 'subitems' in revealOptions ? revealOptions.subitems : []; - revealItems.push({description: 'All', event: () => {this.setFilterMode(cardMode.ALL);}, icon: 'layer-group',}); // prettier-ignore - revealItems.push({description: 'Star', event: () => {this.setFilterMode(cardMode.STAR);}, icon: 'star',}); // prettier-ignore - revealItems.push({description: 'Practice Mode', event: () => {this.setFilterMode(cardMode.PRACTICE);}, icon: 'check',}); // prettier-ignore - cm.addItem({description: 'Quiz Cards', event: () => {this.setFilterMode(cardMode.QUIZ);}, icon: 'pencil',}); // prettier-ignore - !revealOptions && cm.addItem({ description: 'Filter Flashcards', addDivider: false, noexpand: true, subitems: revealItems, icon: 'layer-group' }); - //cm.addItem({description: 'Quiz Cards', event: () => {this.layoutDoc.filterOp = cardMode.QUIZ; this.clearContent()}); - }; + // const revealOptions = cm.findByDescription('Filter Flashcards'); + // const revealItems: ContextMenuProps[] = revealOptions && 'subitems' in revealOptions ? revealOptions.subitems : []; + // revealItems.push({description: 'All', event: () => {this.setFilterMode(cardMode.ALL);}, icon: 'layer-group',}); // prettier-ignore + // revealItems.push({description: 'Star', event: () => {this.setFilterMode(cardMode.STAR);}, icon: 'star',}); // prettier-ignore + // revealItems.push({description: 'Practice Mode', event: () => {this.setFilterMode(cardMode.PRACTICE);}, icon: 'check',}); // prettier-ignore + // cm.addItem({description: 'Quiz Cards', event: () => {this.setFilterMode(cardMode.QUIZ);}, icon: 'pencil',}); // prettier-ignore + // !revealOptions && cm.addItem({ description: 'Filter Flashcards', addDivider: false, noexpand: true, subitems: revealItems, icon: 'layer-group' }); + // //cm.addItem({description: 'Quiz Cards', event: () => {this.layoutDoc.filterOp = cardMode.QUIZ; this.clearContent()}); + // }; @computed get content() { const index = NumCast(this.layoutDoc._carousel_index); const curDoc = this.carouselItems?.[index]; @@ -226,6 +231,28 @@ export class CollectionCarouselView extends CollectionSubView() { ); } + @computed get menu() { + return ( + <div className="carouselView-menu"> + <Tooltip title="Practice flashcards using GPT"> + <div key="back" className="carouselView-quiz" onClick={e => (this.layoutDoc.filterOp === cardMode.QUIZ ? this.setFilterMode(cardMode.ALL) : this.setFilterMode(cardMode.QUIZ))}> + <FontAwesomeIcon icon="file-pen" color={this.layoutDoc.filterOp === cardMode.QUIZ ? 'white' : 'light gray'} size="1x" /> + </div> + </Tooltip> + <Tooltip title={this.layoutDoc.filterOp === cardMode.PRACTICE ? 'Exit practice mode' : 'Practice flashcards manually'}> + <div key="back" className="carouselView-practice" onClick={e => (this.layoutDoc.filterOp === cardMode.PRACTICE ? this.setFilterMode(cardMode.ALL) : this.setFilterMode(cardMode.PRACTICE))}> + <FontAwesomeIcon icon="check" color={this.layoutDoc.filterOp === cardMode.PRACTICE ? 'white' : 'light gray'} size="1x" /> + </div> + </Tooltip> + <Tooltip title={this.layoutDoc.filterOp === cardMode.STAR ? 'Show all cards' : 'Show only starred cards'}> + <div key="back" className="carouselView-starFilter" onClick={e => (!this.layoutDoc.filterOp ? this.setFilterMode(cardMode.ALL) : this.setFilterMode(cardMode.STAR))}> + <FontAwesomeIcon icon="filter" color={this.layoutDoc.filterOp === cardMode.STAR || !this.layoutDoc.filterOp ? 'white' : 'light gray'} size="1x" /> + </div> + </Tooltip> + </div> + ); + } + render() { return ( <div @@ -250,6 +277,7 @@ export class CollectionCarouselView extends CollectionSubView() { <p style={{ color: 'red', + fontWeight: 'bold', zIndex: '999', position: 'relative', left: '10px', @@ -263,6 +291,7 @@ export class CollectionCarouselView extends CollectionSubView() { }}> Recently missed! </p> + {this.menu} {this.Document._chromeHidden || !this.layoutDoc.filterOp ? null : this.buttons} </div> ); diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index f844892c5..084723d56 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -45,6 +45,9 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() @observable private _loading = false; @observable private _errorMessage = ''; @observable private _outputMessage = ''; + @observable private _isEmpty = false; + + public addToCollection: ((doc: Doc | Doc[], annotationKey?: string | undefined) => boolean) | undefined; @action handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { this._inputValue = e.target.value; @@ -162,23 +165,29 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() }; clearDoc = undoable((fieldKey: string) => { - delete this.dataDoc[fieldKey]; - this.dataDoc[fieldKey] = 'empty'; + // delete this.dataDoc[fieldKey]; + this.dataDoc[fieldKey] = undefined; + this._isEmpty = true; + // this.dataDoc[fieldKey] = 'empty'; + console.log('HERE' + fieldKey + ';'); }, 'clear doc'); // clearDoc = (fieldKey: string) => delete this.dataDoc[fieldKey]; moveDoc = (doc: Doc, addDocument: (document: Doc | Doc[]) => boolean, which: string) => this.remDoc(doc, which) && addDocument(doc); addDoc = (doc: Doc, which: string) => { - if (this.dataDoc[which] && this.dataDoc[which] !== 'empty') return false; + if (this.dataDoc[which] && !this._isEmpty) return false; this.dataDoc[which] = doc; return true; }; remDoc = (doc: Doc, which: string) => { if (this.dataDoc[which] === doc) { - this.dataDoc[which] = 'empty'; + this._isEmpty = true; + // this.dataDoc[which] = 'empty'; + console.log('HEREEEE'); this.dataDoc[which] = undefined; return true; } + console.log('FALSE'); return false; }; @@ -268,8 +277,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() if (!this.layoutDoc[`_${this._props.fieldKey}_revealOp`] || this.layoutDoc[`_${this._props.fieldKey}_revealOp`] === 'flip') { this.flipFlashcard(); - console.log('Print Front of cards: ' + (RTFCast(DocCast(this.dataDoc[this.fieldKey + '_0']).text)?.Text ?? '')); - console.log('Print Back of cards: ' + (RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text ?? '')); + // console.log('Print Front of cards: ' + (RTFCast(DocCast(this.dataDoc[this.fieldKey + '_0']).text)?.Text ?? '')); + // console.log('Print Back of cards: ' + (RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text ?? '')); } }) } @@ -297,10 +306,31 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() <div className="dash-tooltip">Ask GPT to create an answer on the back side of the flashcard</div> ) }> - <div style={{ position: 'absolute', bottom: '3px', right: '55px', cursor: 'pointer' }} onPointerDown={e => (!this.layoutDoc[`_${this._props.fieldKey}_usePath`] ? this.askGPT(GPTCallType.CHATCARD) : null)}> + <div style={{ position: 'absolute', bottom: '3px', right: '56px', 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 => { + 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), + _layout_fitWidth: false, + _layout_autoHeight: true, + }); + newCol['x'] = e.clientX - 820; + newCol['y'] = e.clientY - 640; + this._props.addDocument?.(newCol); + this._props.removeDocument?.(this.Document); + this.Document.embedContainer = newCol; + }}> + <FontAwesomeIcon icon="folder-plus" size="xl" /> + </div> + </Tooltip> <Tooltip title={<div className="dash-tooltip">Hover to reveal</div>}> <div style={{ position: 'absolute', bottom: '3px', right: '25px', cursor: 'pointer' }} @@ -308,11 +338,18 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() <FontAwesomeIcon color={this.revealOp === 'hover' ? 'blue' : 'black'} icon="layer-group" size="xl" /> </div> </Tooltip> - {this.overlayAlternateIcon} + {/* <Tooltip title={<div className="dash-tooltip">Remove this side of the flashcard</div>}> + <div + style={{ position: 'absolute', bottom: '3px', right: '80px', cursor: 'pointer' }} + onPointerDown={e => this.closeDown(e, this.layoutDoc[`_${this._props.fieldKey}_usePath`] === 'alternate' ? this._props.fieldKey + '_1' : this._props.fieldKey + '_0')}> + <FontAwesomeIcon color={this.revealOp === 'hover' ? 'blue' : 'black'} icon="trash-can" size="xl" /> + </div> + </Tooltip> */} + {/* {this.overlayAlternateIcon} */} </div> ); } - + // this.closeDown(e, this.layoutDoc[`_${this._props.fieldKey}_usePath`] === 'alternate' ? this.fieldKey + '_0' : this.fieldKey + '_1')} @action activateContent = () => { this.childActive = true; }; @@ -434,7 +471,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() hideLinkButton pointerEvents={this.childActive ? undefined : returnNone} /> - <div style={{ position: 'absolute', top: '-5px', left: '2px' }}>{layoutString ? null : clearButton(whichSlot)}</div> + {/* <div style={{ position: 'absolute', top: '-5px', left: '2px' }}>{layoutString ? null : clearButton(whichSlot)}</div> */} </> // placeholder image if doc is missingleft: `${NumCast(this.layoutDoc.width, 200) - 33}px` ) : ( <div className="placeholder"> @@ -452,7 +489,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() this.activateContent(); }} ref={ele => this.createDropTarget(ele, which, index)}> - {displayDoc(which)} + {!this._isEmpty ? displayDoc(which) : null} + {/* {this.dataDoc[this.fieldKey + '_0'] !== 'empty' ? displayDoc(which) : null} */} </div> ); @@ -460,7 +498,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() const side = this.layoutDoc[`_${this._props.fieldKey}_usePath`] === 'alternate' ? 1 : 0; // add text box to each side when comparison box is first created - if (!(this.dataDoc[this.fieldKey + '_0'] || this.dataDoc[this.fieldKey + '_0'] === 'empty')) { + // (!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 newDoc = Docs.Create.TextDocument(dataSplit[1]); // if there is text from the pdf ai cards, put the question on the front side. @@ -468,7 +507,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() newDoc[DocData].text = dataSplit[1]; this.addDoc(newDoc, this.fieldKey + '_0'); } - if (!(this.dataDoc[this.fieldKey + '_1'] || this.dataDoc[this.fieldKey + '_1'] === 'empty')) { + if (!this.dataDoc[this.fieldKey + '_1'] && !this._isEmpty) { const dataSplit = StrCast(this.dataDoc.data).split('Answer'); const newDoc = Docs.Create.TextDocument(dataSplit[0]); // if there is text from the pdf ai cards, put the answer on the alternate side. @@ -478,6 +517,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() } // render the QuizCards + console.log('GERE' + DocCast(this.Document.embedContainer).filterOp); if (DocCast(this.Document.embedContainer) && DocCast(this.Document.embedContainer).filterOp === 'quiz') { const text = StrCast(RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text); return ( @@ -489,6 +529,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() value={this.layoutDoc[`_${this._props.fieldKey}_usePath`] === 'alternate' ? this._outputValue : this._inputValue} onChange={this.handleInputChange} onScroll={e => e.stopPropagation()} + placeholder={!this.layoutDoc[`_${this._props.fieldKey}_usePath`] ? 'Enter a response for GPT to evaluate.' : ''} readOnly={this.layoutDoc[`_${this._props.fieldKey}_usePath`] === 'alternate'}></textarea> {this._loading ? ( @@ -516,7 +557,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() <div className={`comparisonBox${this._props.isContentActive() ? '-interactive' : ''}`} /* change className to easily disable/enable pointer events in CSS */ // onContextMenu={this.specificMenu} - style={{ display: 'flex', flexDirection: 'column' }} + style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden' }} onMouseEnter={() => { this.hoverFlip('alternate'); }} @@ -531,8 +572,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>() <ReactLoading type="spin" height={30} width={30} color={'blue'} /> </div> ) : null} - {this.flashcardMenu} - {/* {this.overlayAlternateIcon} */} + {this._props.isContentActive() ? this.flashcardMenu : null} + {this.overlayAlternateIcon} </div> ); } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 2f3357791..d4c31a5b3 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -566,13 +566,13 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document !appearance && appearanceItems.length && cm.addItem({ description: 'Appearance...', subitems: appearanceItems, icon: 'compass' }); // creates menu for the user to select how to reveal the flashcards - if (this.Document._layout_isFlashcard) { - const revealOptions = cm.findByDescription('Reveal Options'); - const revealItems: ContextMenuProps[] = revealOptions && 'subitems' in revealOptions ? revealOptions.subitems : []; - revealItems.push({ description: 'Hover', event: () => { this.layoutDoc[`_${this._props.fieldKey}_revealOp`] = 'hover'; }, icon: 'hand-point-up' }); // prettier-ignore - revealItems.push({ description: 'Flip', event: () => { this.layoutDoc[`_${this._props.fieldKey}_revealOp`] = 'flip'; }, icon: 'rotate' }); // prettier-ignore - !revealOptions && cm.addItem({ description: 'Reveal Options', addDivider: false, noexpand: true, subitems: revealItems, icon: 'layer-group' }); - } + // if (this.Document._layout_isFlashcard) { + // const revealOptions = cm.findByDescription('Reveal Options'); + // const revealItems: ContextMenuProps[] = revealOptions && 'subitems' in revealOptions ? revealOptions.subitems : []; + // revealItems.push({ description: 'Hover', event: () => { this.layoutDoc[`_${this._props.fieldKey}_revealOp`] = 'hover'; }, icon: 'hand-point-up' }); // prettier-ignore + // revealItems.push({ description: 'Flip', event: () => { this.layoutDoc[`_${this._props.fieldKey}_revealOp`] = 'flip'; }, icon: 'rotate' }); // prettier-ignore + // !revealOptions && cm.addItem({ description: 'Reveal Options', addDivider: false, noexpand: true, subitems: revealItems, icon: 'layer-group' }); + // } if (this._props.bringToFront) { const zorders = cm.findByDescription('ZOrder...'); |