aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/pdf/AnchorMenu.tsx
diff options
context:
space:
mode:
authoralyssaf16 <alyssa_feinberg@brown.edu>2024-10-06 15:15:06 -0400
committeralyssaf16 <alyssa_feinberg@brown.edu>2024-10-06 15:15:06 -0400
commitfbff73033b6c0f9b1214e9013c155ff085e7a737 (patch)
treee5a278de98cb71fa023af7b85e20aafaf5ab03bf /src/client/views/pdf/AnchorMenu.tsx
parentfa54fdf2bf9bf8523da393a81ec1ac1cd4fa0f4c (diff)
parente61b2b356e761dfefda9d09bbbfc3c4a8d943f2c (diff)
Merge branch 'alyssa-starter' of https://github.com/brown-dash/Dash-Web into alyssa-starter
Diffstat (limited to 'src/client/views/pdf/AnchorMenu.tsx')
-rw-r--r--src/client/views/pdf/AnchorMenu.tsx51
1 files changed, 46 insertions, 5 deletions
diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx
index 6dd036cf6..bff112017 100644
--- a/src/client/views/pdf/AnchorMenu.tsx
+++ b/src/client/views/pdf/AnchorMenu.tsx
@@ -1,21 +1,24 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { ColorPicker, Group, IconButton, Popup, Size, Toggle, ToggleType, Type } from 'browndash-components';
-import { IReactionDisposer, ObservableMap, action, computed, makeObservable, observable, reaction } from 'mobx';
+import { IReactionDisposer, ObservableMap, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { ColorResult } from 'react-color';
+import ReactLoading from 'react-loading';
import { ClientUtils, returnFalse, setupMoveUpEvents } from '../../../ClientUtils';
import { emptyFunction, unimplementedFunction } from '../../../Utils';
import { Doc, Opt } from '../../../fields/Doc';
+import { DocData } from '../../../fields/DocSymbols';
import { GPTCallType, gptAPICall } from '../../apis/gpt/GPT';
import { Docs } from '../../documents/Documents';
import { SettingsManager } from '../../util/SettingsManager';
+import { undoBatch } from '../../util/UndoManager';
import { AntimodeMenu, AntimodeMenuProps } from '../AntimodeMenu';
import { LinkPopup } from '../linking/LinkPopup';
import { DocumentView } from '../nodes/DocumentView';
+import { DrawingOptions, SmartDrawHandler } from '../smartdraw/SmartDrawHandler';
import './AnchorMenu.scss';
import { GPTPopup, GPTPopupMode } from './GPTPopup/GPTPopup';
-import ReactLoading from 'react-loading';
@observer
export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
@@ -44,6 +47,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
@observable private _selectedText: string = '';
@observable private _x: number = 0;
@observable private _y: number = 0;
+ @observable private _isLoading: boolean = false;
@action
public setSelectedText = (txt: string) => {
this._selectedText = txt.trim();
@@ -78,6 +82,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
public get Active() {
return this._left > 0;
}
+ public AddDrawingAnnotation: (doc: Doc) => void = unimplementedFunction;
public addToCollection: ((doc: Doc | Doc[], annotationKey?: string | undefined) => boolean) | undefined;
componentWillUnmount() {
@@ -137,10 +142,9 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
transferToFlashcard = (text: string, x: number, y: number) => {
// put each question generated by GPT on the front of the flashcard
- var senArr = text.trim().split('Question: ');
- var collectionArr: Doc[] = [];
+ const senArr = text.trim().split('Question: ');
+ const 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 });
newDoc.text = senArr[i];
@@ -164,6 +168,35 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
this._loading = false;
};
+ /**
+ * Creates a GPT drawing based on selected text.
+ */
+ gptDraw = async (e: React.PointerEvent) => {
+ try {
+ SmartDrawHandler.Instance.AddDrawing = this.createDrawingAnnotation;
+ runInAction(() => (this._isLoading = true));
+ await SmartDrawHandler.Instance.drawWithGPT({ X: e.clientX, Y: e.clientY }, this._selectedText, 5, 100, true);
+ runInAction(() => (this._isLoading = false));
+ } catch (err) {
+ console.error(err);
+ }
+ };
+
+ /**
+ * Defines how a GPT drawing should be added to the current document.
+ */
+ @undoBatch
+ createDrawingAnnotation = action((drawing: Doc, opts: DrawingOptions, gptRes: string) => {
+ this.AddDrawingAnnotation(drawing);
+ const docData = drawing[DocData];
+ docData.title = opts.text.match(/^(.*?)~~~.*$/)?.[1] || opts.text;
+ docData.drawingInput = opts.text;
+ docData.drawingComplexity = opts.complexity;
+ docData.drawingColored = opts.autoColor;
+ docData.drawingSize = opts.size;
+ docData.drawingData = gptRes;
+ });
+
pointerDown = (e: React.PointerEvent) => {
setupMoveUpEvents(
this,
@@ -249,6 +282,14 @@ 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} icon={<FontAwesomeIcon icon="id-card" size="lg" />} color={SettingsManager.userColor} />
<IconButton tooltip="Create labels" onPointerDown={this.makeLabels} icon={<FontAwesomeIcon icon="tag" size="lg" />} color={SettingsManager.userColor} />
+ {this._selectedText && (
+ <IconButton
+ tooltip="Create drawing"
+ onPointerDown={e => this.gptDraw(e)}
+ icon={this._isLoading ? <ReactLoading type="spin" color={SettingsManager.userVariantColor} width={16} height={20} /> : <FontAwesomeIcon icon="paintbrush" size="lg" />}
+ color={SettingsManager.userColor}
+ />
+ )}
{AnchorMenu.Instance.OnAudio === unimplementedFunction ? null : (
<IconButton
tooltip="Click to Record Annotation" //