aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/smartdraw/AnnotationPalette.tsx
diff options
context:
space:
mode:
authoreleanor-park <eleanor_park@brown.edu>2024-07-11 11:50:01 -0400
committereleanor-park <eleanor_park@brown.edu>2024-07-11 11:50:01 -0400
commit49b3c7cbe01f830a2b1d2c02452901fe360348d3 (patch)
treead4efc73fac5e2dfa20b1911399821614f42fa8c /src/client/views/smartdraw/AnnotationPalette.tsx
parentf33e6c9e191092e6050f980892b4404ff0d0a1f2 (diff)
updates
Diffstat (limited to 'src/client/views/smartdraw/AnnotationPalette.tsx')
-rw-r--r--src/client/views/smartdraw/AnnotationPalette.tsx337
1 files changed, 337 insertions, 0 deletions
diff --git a/src/client/views/smartdraw/AnnotationPalette.tsx b/src/client/views/smartdraw/AnnotationPalette.tsx
new file mode 100644
index 000000000..10e88e91e
--- /dev/null
+++ b/src/client/views/smartdraw/AnnotationPalette.tsx
@@ -0,0 +1,337 @@
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { flexibleCompare } from '@fullcalendar/core/internal';
+import { Slider, Switch } from '@mui/material';
+import { Button, IconButton } from 'browndash-components';
+import { data } from 'jquery';
+import { action, computed, makeObservable, observable } from 'mobx';
+import { observer } from 'mobx-react';
+import * as React from 'react';
+import { AiOutlineSend } from 'react-icons/ai';
+import ReactLoading from 'react-loading';
+import { returnAll, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, returnTrue, returnZero } from '../../../ClientUtils';
+import { ActiveInkWidth, Doc, StrListCast } from '../../../fields/Doc';
+import { DocData } from '../../../fields/DocSymbols';
+import { InkData, InkField } from '../../../fields/InkField';
+import { BoolCast, DocCast } from '../../../fields/Types';
+import { emptyFunction } from '../../../Utils';
+import { Docs } from '../../documents/Documents';
+import { CollectionViewType } from '../../documents/DocumentTypes';
+import { DragManager } from '../../util/DragManager';
+import { convertDropDataToButtons, makeUserTemplateButton } from '../../util/DropConverter';
+import { SettingsManager } from '../../util/SettingsManager';
+import { Transform } from '../../util/Transform';
+import { MarqueeOptionsMenu, MarqueeView } from '../collections/collectionFreeForm';
+import { CollectionGridView } from '../collections/collectionGrid';
+import { CollectionStackingView } from '../collections/CollectionStackingView';
+import { DocumentView, DocumentViewInternal } from '../nodes/DocumentView';
+import { FieldViewProps } from '../nodes/FieldView';
+import { ObservableReactComponent } from '../ObservableReactComponent';
+import { DefaultStyleProvider } from '../StyleProvider';
+import './AnnotationPalette.scss';
+import { SmartDrawHandler } from './SmartDrawHandler';
+
+@observer
+export class AnnotationPalette extends ObservableReactComponent<{}> {
+ static Instance: AnnotationPalette;
+ @observable private _savedDrawings: Doc[] = [];
+ // @observable private _marqueeViewRef = React.createRef<MarqueeView>();
+ @observable private _display: boolean = false;
+ @observable private _paletteMode: 'create' | 'view' = 'view';
+ @observable private _userInput: string = '';
+ @observable private _showDrawing: boolean = false;
+ @observable private _drawing: Doc | undefined = undefined;
+ @observable private _isLoading: boolean = false;
+ @observable private _detail: number = 5;
+ @observable private _size: number = 350;
+ @observable private _canInteract: boolean = true;
+
+ constructor(props: any) {
+ super(props);
+ makeObservable(this);
+ AnnotationPalette.Instance = this;
+ }
+
+ return170 = () => 170;
+
+ @action
+ setPaletteMode = (mode: 'create' | 'view') => {
+ this._paletteMode = mode;
+ };
+
+ @action
+ setUserInput = (input: string) => {
+ this._userInput = input;
+ };
+
+ @action
+ setDetail = (detail: number) => {
+ this._detail = detail;
+ };
+
+ @action
+ setSize = (size: number) => {
+ this._size = size;
+ };
+
+ saveAnno = async (docView: DocumentView | undefined, doc: Doc) => {
+ const dragData = new DragManager.DocumentDragData([doc]);
+ // convertDropDataToButtons(dragData);
+ const clone = await Doc.MakeClone(doc);
+ clone.clone.title = doc.title;
+ const templateBtn = makeUserTemplateButton(clone.clone);
+
+ // const cloneData: Doc = DocCast(clone.clone[DocData]);
+ // cloneData.dragFactory = doc;
+ Doc.AddDocToList(Doc.MyAnnos, 'data', templateBtn);
+ // const collection = this._marqueeViewRef.current?.collection(undefined, false, this._savedDrawings);
+ // if (docView) docView.ComponentView?.removeDocument?.(doc);
+ };
+
+ @action
+ displayPalette = (display: boolean) => {
+ this._display = display;
+ };
+
+ @action
+ generateDrawing = async () => {
+ this._isLoading = true;
+ try {
+ const drawingRes = await SmartDrawHandler.Instance.drawWithGPT({ X: 0, Y: 0 }, this._userInput);
+ const opts = drawingRes?.lastInput;
+ const drawing: Doc[] = [];
+ drawingRes?.data.forEach((stroke: [InkData, string, string]) => {
+ const bounds = InkField.getBounds(stroke[0]);
+ // const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height);
+ const inkWidth = ActiveInkWidth();
+ const inkDoc = Docs.Create.InkDocument(
+ stroke[0],
+ { title: 'stroke',
+ // x: B.x - inkWidth / 2,
+ // y: B.y - inkWidth / 2,
+ // _width: B.width + inkWidth,
+ // _height: B.height + inkWidth,
+ stroke_showLabel: BoolCast(Doc.UserDoc().activeInkHideTextLabels)}, // prettier-ignore
+ inkWidth,
+ stroke[1],
+ undefined,
+ stroke[2] === 'none' ? undefined : stroke[2]
+ );
+ drawing.push(inkDoc);
+ });
+ const collection = MarqueeOptionsMenu.Instance.createCollection(undefined, true, drawing);
+ if (collection) {
+ const docData = collection[DocData];
+ docData.title = opts?.text;
+ docData.drawingInput = opts?.text;
+ docData.drawingComplexity = opts?.complexity;
+ docData.drawingColored = opts?.autoColor;
+ docData.drawingSize = opts?.size;
+ docData.drawingData = drawingRes?.lastRes;
+ this._drawing = collection;
+ }
+ this._showDrawing = true;
+ } catch (e) {
+ console.log('Error generating drawing');
+ }
+ this._isLoading = false;
+ };
+
+ // @computed get drawingCreator() {
+ // return (
+ // MarqueeOptionsMenu.Instance.createCollection(undefined, true, this._drawing);
+ // );
+ // }
+ // return Docs.Create.FreeformDocument([], {});
+ // Docs.Create.
+ // return (
+ // <DocumentView
+ // Document={doc}
+ // addDocument={undefined}
+ // addDocTab={DocumentViewInternal.addDocTabFunc}
+ // pinToPres={DocumentView.PinDoc}
+ // containerViewPath={returnEmptyDoclist}
+ // styleProvider={DefaultStyleProvider}
+ // removeDocument={returnFalse}
+ // ScreenToLocalTransform={Transform.Identity}
+ // PanelWidth={this.return170}
+ // PanelHeight={this.return170}
+ // renderDepth={0}
+ // isContentActive={returnTrue}
+ // focus={emptyFunction}
+ // whenChildContentsActiveChanged={emptyFunction}
+ // childFilters={returnEmptyFilter}
+ // childFiltersByRanges={returnEmptyFilter}
+ // searchFilterDocs={returnEmptyDoclist}
+ // />
+ // );
+
+ render() {
+ return !this._display ? null : (
+ <div className="annotation-palette" style={{ zIndex: 1000 }}>
+ {this._paletteMode === 'view' && (
+ <>
+ <DocumentView
+ Document={Doc.MyAnnos}
+ addDocument={undefined}
+ addDocTab={DocumentViewInternal.addDocTabFunc}
+ pinToPres={DocumentView.PinDoc}
+ containerViewPath={returnEmptyDoclist}
+ styleProvider={DefaultStyleProvider}
+ removeDocument={returnFalse}
+ ScreenToLocalTransform={Transform.Identity}
+ PanelWidth={this.return170}
+ PanelHeight={this.return170}
+ renderDepth={0}
+ isContentActive={returnTrue}
+ focus={emptyFunction}
+ whenChildContentsActiveChanged={emptyFunction}
+ childFilters={returnEmptyFilter}
+ childFiltersByRanges={returnEmptyFilter}
+ searchFilterDocs={returnEmptyDoclist}
+ />
+ <Button
+ // style={{ alignSelf: 'center' }}
+ text="Add"
+ icon={<FontAwesomeIcon icon="square-plus" />}
+ // iconPlacement=""
+ color={SettingsManager.userColor}
+ onClick={() => this.setPaletteMode('create')}
+ />
+ </>
+ )}
+ {this._paletteMode === 'create' && (
+ <>
+ <div style={{ display: 'flex', flexDirection: 'row', width: '170px' }}>
+ {/* <IconButton
+ tooltip="Advanced Options"
+ icon={<FontAwesomeIcon icon="caret-right" />}
+ color={SettingsManager.userColor}
+ style={{ width: '14px' }}
+ // onClick={() => {
+ // this._showOptions = !this._showOptions;
+ // }}
+ /> */}
+ <input
+ aria-label="label-input"
+ id="new-label"
+ type="text"
+ style={{ color: 'black', width: '170px' }}
+ value={this._userInput}
+ onChange={e => {
+ this.setUserInput(e.target.value);
+ }}
+ placeholder="Enter item to draw"
+ // onKeyDown={this.handleKeyPress}
+ />
+ <Button
+ style={{ alignSelf: 'flex-end' }}
+ // text="Send"
+ icon={this._isLoading ? <ReactLoading type="spin" color={SettingsManager.userVariantColor} width={16} height={20} /> : <AiOutlineSend />}
+ iconPlacement="right"
+ color={SettingsManager.userColor}
+ onClick={this.generateDrawing}
+ />
+ </div>
+ <div style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between', width: '170px', marginTop: '5px' }}>
+ <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', width: '40px' }}>
+ Color
+ <Switch
+ sx={{
+ '& .MuiSwitch-switchBase.Mui-checked': {
+ color: SettingsManager.userColor,
+ },
+ '& .MuiSwitch-switchBase.Mui-checked + .MuiSwitch-track': {
+ backgroundColor: SettingsManager.userVariantColor,
+ },
+ }}
+ defaultChecked={true}
+ size="small"
+ // onChange={this.setAutoColor}
+ />
+ </div>
+ <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', width: '60px' }}>
+ Detail
+ <Slider
+ sx={{
+ '& .MuiSlider-thumb': {
+ color: SettingsManager.userColor,
+ '&.Mui-focusVisible, &:hover, &.Mui-active': {
+ boxShadow: `0px 0px 0px 8px${SettingsManager.userColor.slice(0, 7)}10`,
+ },
+ },
+ '& .MuiSlider-track': {
+ color: SettingsManager.userVariantColor,
+ },
+ '& .MuiSlider-rail': {
+ color: SettingsManager.userColor,
+ },
+ }}
+ style={{ width: '80%' }}
+ min={1}
+ max={10}
+ step={1}
+ size="small"
+ value={this._detail}
+ onChange={(e, val) => {
+ this.setDetail(val as number);
+ }}
+ valueLabelDisplay="auto"
+ />
+ </div>
+ <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', width: '60px' }}>
+ Size
+ <Slider
+ sx={{
+ '& .MuiSlider-thumb': {
+ color: SettingsManager.userColor,
+ '&.Mui-focusVisible, &:hover, &.Mui-active': {
+ boxShadow: `0px 0px 0px 8px${SettingsManager.userColor.slice(0, 7)}20`,
+ },
+ },
+ '& .MuiSlider-track': {
+ color: SettingsManager.userVariantColor,
+ },
+ '& .MuiSlider-rail': {
+ color: SettingsManager.userColor,
+ },
+ }}
+ style={{ width: '80%' }}
+ min={50}
+ max={700}
+ step={10}
+ size="small"
+ value={this._size}
+ onChange={(e, val) => {
+ this.setSize(val as number);
+ }}
+ valueLabelDisplay="auto"
+ />
+ </div>
+ </div>
+ {this._drawing !== undefined && (
+ <DocumentView
+ Document={this._drawing}
+ addDocument={undefined}
+ addDocTab={DocumentViewInternal.addDocTabFunc}
+ pinToPres={DocumentView.PinDoc}
+ containerViewPath={returnEmptyDoclist}
+ styleProvider={DefaultStyleProvider}
+ removeDocument={returnFalse}
+ ScreenToLocalTransform={Transform.Identity}
+ PanelWidth={this.return170}
+ PanelHeight={this.return170}
+ renderDepth={0}
+ isContentActive={returnTrue}
+ focus={emptyFunction}
+ whenChildContentsActiveChanged={emptyFunction}
+ childFilters={returnEmptyFilter}
+ childFiltersByRanges={returnEmptyFilter}
+ searchFilterDocs={returnEmptyDoclist}
+ />
+ )}
+ </>
+ )}
+ </div>
+ );
+ }
+}