aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/util/CurrentUserUtils.ts28
-rw-r--r--src/client/util/bezierFit.ts1
-rw-r--r--src/client/views/DocumentButtonBar.tsx25
-rw-r--r--src/client/views/GlobalKeyHandler.ts2
-rw-r--r--src/client/views/LightboxView.tsx7
-rw-r--r--src/client/views/MainView.tsx10
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx18
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx3
-rw-r--r--src/client/views/smartdraw/AnnotationPalette.scss10
-rw-r--r--src/client/views/smartdraw/AnnotationPalette.tsx337
-rw-r--r--src/client/views/smartdraw/DrawingPalette.scss11
-rw-r--r--src/client/views/smartdraw/DrawingPalette.tsx89
-rw-r--r--src/client/views/smartdraw/SmartDrawHandler.scss3
-rw-r--r--src/client/views/smartdraw/SmartDrawHandler.tsx95
-rw-r--r--src/fields/Doc.ts6
15 files changed, 493 insertions, 152 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 141695d86..24a5de42b 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -162,6 +162,33 @@ export class CurrentUserUtils {
const reqdScripts = { dropConverter: "convertToButtons(dragData)" };
return DocUtils.AssignDocField(doc, field, (opts,items) => Docs.Create.TreeDocument(items??[], opts), reqdOpts, templates, reqdScripts);
}
+
+ static setupAnnoPalette(doc: Doc, field="myAnnos") {
+ const reqdOpts:DocumentOptions = {
+ title: "Saved Annotations", _xMargin: 0, _layout_showTitle: "title", _chromeHidden: true, hidden: false,
+ _dragOnlyWithinContainer: true, layout_hideContextMenu: true, isSystem: true, _forceActive: true,
+ _layout_autoHeight: true, _width: 500, _height: 300, _layout_fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true,
+ };
+ const reqdScripts = { dropConverter: "convertToButtons(dragData)" };
+ const savedAnnos = DocCast(doc[field]);
+ return DocUtils.AssignDocField(doc, field, (opts,items) => Docs.Create.MasonryDocument(items??[], opts), reqdOpts, DocListCast(savedAnnos?.data), reqdScripts);
+ }
+
+ // static setupNoteTemplates(doc: Doc, field="template_notes") {
+ // const tempNotes = DocCast(doc[field]);
+ // const reqdTempOpts:DocumentOptions[] = [
+ // { title: "Postit", backgroundColor: "yellow", icon: "sticky-note", _layout_showTitle: "title", layout_borderRounding: "5px"},
+ // { title: "Idea", backgroundColor: "pink", icon: "lightbulb" , _layout_showTitle: "title"},
+ // { title: "Topic", backgroundColor: "lightblue", icon: "book-open" , _layout_showTitle: "title"}];
+ // const reqdNoteList = [...reqdTempOpts.map(opts => {
+ // const reqdOpts = {...opts, isSystem:true, width:200, layout_autoHeight: true, layout_fitWidth: true};
+ // const noteTemp = tempNotes ? DocListCast(tempNotes.data).find(fdoc => fdoc.title === opts.title): undefined;
+ // return DocUtils.AssignOpts(noteTemp, reqdOpts) ?? MakeTemplate(Docs.Create.TextDocument("",reqdOpts));
+ // }), ... DocListCast(tempNotes?.data).filter(note => !reqdTempOpts.find(reqd => reqd.title === note.title))];
+
+ // const reqdOpts:DocumentOptions = { title: "Note Layouts", _height: 75, isSystem: true };
+ // // eslint-disable-next-line no-return-assign
+ // r
// setup templates for different document types when they are iconified from Document Decorations
static setupDefaultIconTemplates(doc: Doc, field="template_icons") {
@@ -986,6 +1013,7 @@ pie title Minerals in my tap water
this.setupTopbarButtons(doc);
this.setupDockedButtons(doc); // the bottom bar of font icons
this.setupLeftSidebarMenu(doc); // the left-side column of buttons that open their contents in a flyout panel on the left
+ this.setupAnnoPalette(doc);
this.setupDocTemplates(doc); // sets up the template menu of templates
// sthis.setupFieldInfos(doc); // sets up the collection of field info descriptions for each possible DocumentOption
DocUtils.AssignDocField(doc, "globalScriptDatabase", () => Docs.Prototypes.MainScriptDocument(), {});
diff --git a/src/client/util/bezierFit.ts b/src/client/util/bezierFit.ts
index f5696afaf..98a6feea0 100644
--- a/src/client/util/bezierFit.ts
+++ b/src/client/util/bezierFit.ts
@@ -627,7 +627,6 @@ export function GenerateControlPoints(coordinates: Point[], alpha = 0.1) {
}
export function SVGToBezier(name: SVGType, attributes: any): Point[] {
- console.log('in svg to bezier', name, attributes);
switch (name) {
case 'line':
const x1 = parseInt(attributes.x1);
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 487868169..177546fdc 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -12,7 +12,7 @@ import * as React from 'react';
import { FaEdit } from 'react-icons/fa';
import { returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick } from '../../ClientUtils';
import { emptyFunction } from '../../Utils';
-import { Doc } from '../../fields/Doc';
+import { Doc, DocListCast } from '../../fields/Doc';
import { Cast, DocCast } from '../../fields/Types';
import { DocUtils, IsFollowLinkScript } from '../documents/DocUtils';
import { CalendarManager } from '../util/CalendarManager';
@@ -31,6 +31,8 @@ import { DocumentLinksButton } from './nodes/DocumentLinksButton';
import { DocumentView } from './nodes/DocumentView';
import { OpenWhere } from './nodes/OpenWhere';
import { DashFieldView } from './nodes/formattedText/DashFieldView';
+import { AnnotationPalette } from './smartdraw/AnnotationPalette';
+import { DocData } from '../../fields/DocSymbols';
@observer
export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (DocumentView | undefined)[]; stack?: any }> {
@@ -241,6 +243,26 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (
);
}
+ @observable _annoSaved: boolean = false;
+ @action
+ saveAnno = (targetDoc: Doc) => {
+ targetDoc.savedAsAnno = true;
+ this._annoSaved = true;
+ AnnotationPalette.Instance.saveAnno(this.view0, targetDoc);
+ };
+ @computed
+ get saveAnnoButton() {
+ const targetDoc = this.view0?.Document;
+ if (targetDoc && targetDoc.savedAsAnno) this._annoSaved = true;
+ return !targetDoc ? null : (
+ <Tooltip title={<div className="dash-tooltip">{this._annoSaved ? 'Saved as Annotation!' : 'Save to Annotation Palette'}</div>}>
+ <div className="documentButtonBar-icon" style={{ color: 'white' }} onClick={() => this.saveAnno(targetDoc)}>
+ <FontAwesomeIcon className="documentdecorations-icon" icon={this._annoSaved ? 'clipboard-check' : 'file-arrow-down'} />
+ </div>
+ </Tooltip>
+ );
+ }
+
@computed
get shareButton() {
const targetDoc = this.view0?.Document;
@@ -450,6 +472,7 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (
<div className="documentButtonBar-button">{this.templateButton}</div>
{!DocumentView.Selected().some(v => v.allLinks.length) ? null : <div className="documentButtonBar-button">{this.followLinkButton}</div>}
<div className="documentButtonBar-button">{this.pinButton}</div>
+ <div className="documentButtonBar-button">{this.saveAnnoButton}</div>
<div className="documentButtonBar-button">{this.recordButton}</div>
<div className="documentButtonBar-button">{this.calendarButton}</div>
{!Doc.UserDoc().documentLinksButton_fullMenu ? null : <div className="documentButtonBar-button">{this.shareButton}</div>}
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 7d01bbabb..562827db5 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -162,7 +162,7 @@ export class KeyManager {
case 'delete':
case 'backspace':
if (document.activeElement?.tagName !== 'INPUT' && document.activeElement?.tagName !== 'TEXTAREA') {
- if (DocumentView.LightboxDoc()) {
+ if (DocumentView.LightboxDoc() && !DocumentView.Selected().length) {
DocumentView.SetLightboxDoc(undefined);
DocumentView.DeselectAll();
} else if (!window.getSelection()?.toString()) DocumentDecorations.Instance.onCloseClick(true);
diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx
index e93e4949b..dcd5a61c7 100644
--- a/src/client/views/LightboxView.tsx
+++ b/src/client/views/LightboxView.tsx
@@ -23,7 +23,7 @@ import { DocumentView } from './nodes/DocumentView';
import { OpenWhere, OpenWhereMod } from './nodes/OpenWhere';
import { ScriptingGlobals } from '../util/ScriptingGlobals';
import { OverlayView } from './OverlayView';
-import { DrawingPalette } from './smartdraw/DrawingPalette';
+import { AnnotationPalette } from './smartdraw/AnnotationPalette';
interface LightboxViewProps {
PanelWidth: number;
@@ -73,6 +73,7 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
DocumentView._lightboxContains = LightboxView.Contains;
DocumentView._lightboxDoc = LightboxView.LightboxDoc;
}
+
/**
* Sets the root Doc to render in the lightbox view.
* @param doc
@@ -105,6 +106,8 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
this._history = [];
Doc.ActiveTool = InkTool.None;
SnappingManager.SetExploreMode(false);
+ AnnotationPalette.Instance.displayPalette(false);
+ this._showPalette = false;
}
DocumentView.DeselectAll();
if (future) {
@@ -206,6 +209,7 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
};
togglePalette = () => {
this._showPalette = !this._showPalette;
+ AnnotationPalette.Instance.displayPalette(this._showPalette);
};
togglePen = () => {
Doc.ActiveTool = Doc.ActiveTool === InkTool.Pen ? InkTool.None : InkTool.Pen;
@@ -327,7 +331,6 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
{toggleBtn('lightboxView-paletteBtn', 'toggle annotation palette', this._showPalette === true, 'palette', '', this.togglePalette)}
{toggleBtn('lightboxView-penBtn', 'toggle pen annotation', Doc.ActiveTool === InkTool.Pen, 'pen', '', this.togglePen)}
{toggleBtn('lightboxView-exploreBtn', 'toggle navigate only mode', SnappingManager.ExploreMode, 'globe-americas', '', this.toggleExplore)}
- {this._showPalette && <DrawingPalette />}
</div>
);
}
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 30720a3a2..2e7cb1102 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -77,6 +77,7 @@ import { AnchorMenu } from './pdf/AnchorMenu';
import { GPTPopup } from './pdf/GPTPopup/GPTPopup';
import { TopBar } from './topbar/TopBar';
import { SmartDrawHandler } from './smartdraw/SmartDrawHandler';
+import { AnnotationPalette } from './smartdraw/AnnotationPalette';
const { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } = require('./global/globalCssVariables.module.scss'); // prettier-ignore
const _global = (window /* browser */ || global) /* node */ as any;
@@ -380,6 +381,7 @@ export class MainView extends ObservableReactComponent<{}> {
fa.faXmark,
fa.faExclamation,
fa.faFileAlt,
+ fa.faFileArrowDown,
fa.faFileAudio,
fa.faFileVideo,
fa.faFilePdf,
@@ -434,6 +436,7 @@ export class MainView extends ObservableReactComponent<{}> {
fa.faBold,
fa.faItalic,
fa.faClipboard,
+ fa.faClipboardCheck,
fa.faUnderline,
fa.faStrikethrough,
fa.faSuperscript,
@@ -481,6 +484,7 @@ export class MainView extends ObservableReactComponent<{}> {
fa.faHashtag,
fa.faAlignJustify,
fa.faCheckSquare,
+ fa.faSquarePlus,
fa.faListUl,
fa.faWindowMinimize,
fa.faWindowRestore,
@@ -576,6 +580,9 @@ export class MainView extends ObservableReactComponent<{}> {
Doc.linkFollowUnhighlight();
AudioBox.Enabled = true;
const targets = document.elementsFromPoint(e.x, e.y);
+ const targetClasses: string[] = targets.map(target => {
+ return target.className.toString();
+ });
if (targets.length) {
let targClass = targets[0].className.toString();
for (let i = 0; i < targets.length - 1; i++) {
@@ -583,6 +590,8 @@ export class MainView extends ObservableReactComponent<{}> {
else break;
}
!targClass.includes('contextMenu') && ContextMenu.Instance.closeMenu();
+ !targetClasses.includes('marqueeView') && !targetClasses.includes('smart-draw-handler') && SmartDrawHandler.Instance.hideSmartDrawHandler();
+ !targetClasses.includes('smart-draw-handler') && SmartDrawHandler.Instance.hideRegenerate();
!['timeline-menu-desc', 'timeline-menu-item', 'timeline-menu-input'].includes(targClass) && TimelineMenu.Instance.closeMenu();
}
});
@@ -1106,6 +1115,7 @@ export class MainView extends ObservableReactComponent<{}> {
<GPTPopup key="gptpopup" />
<SchemaCSVPopUp key="schemacsvpopup" />
<GenerativeFill imageEditorOpen={ImageEditor.Open} imageEditorSource={ImageEditor.Source} imageRootDoc={ImageEditor.RootDoc} addDoc={ImageEditor.AddDoc} />
+ <AnnotationPalette />
</div>
);
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 8f8cb9083..3cd1e99ef 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1280,8 +1280,11 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
};
_drawing: Doc[] = [];
+ _drawingContainer: Doc | undefined = undefined;
@undoBatch
- createDrawing = (e: React.PointerEvent<Element>, strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => {
+ createDrawing = (strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => {
+ this._drawing = [];
+ this._drawingContainer = undefined;
strokeData.forEach((stroke: [InkData, string, string]) => {
const bounds = InkField.getBounds(stroke[0]);
const B = this.screenToFreeformContentsXf.transformBounds(bounds.left, bounds.top, bounds.width, bounds.height);
@@ -1305,12 +1308,13 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const collection = this._marqueeViewRef.current?.collection(undefined, true, this._drawing);
if (collection) {
const docData = collection[DocData];
- docData.title = opts.text;
+ docData.title = opts.text.match(/^(.*?)~~~.*$/)?.[0] || opts.text;
docData.drawingInput = opts.text;
docData.drawingComplexity = opts.complexity;
docData.drawingColored = opts.autoColor;
docData.drawingSize = opts.size;
docData.drawingData = gptRes;
+ this._drawingContainer = collection;
}
this._batch?.end();
};
@@ -1318,14 +1322,14 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
removeDrawing = (doc?: Doc) => {
this._batch = UndoManager.StartBatch('regenerateDrawing');
if (doc) {
- const docData: Doc = doc[DocData];
- const children = docData.data as unknown as Doc[];
- this._props.removeDocument?.(doc);
+ const docData = DocCast(doc[DocData]);
+ const children = DocListCast(docData.data);
this._props.removeDocument?.(children);
+ this._props.removeDocument?.(doc);
} else {
this._props.removeDocument?.(this._drawing);
+ if (this._drawingContainer) this._props.removeDocument?.(this._drawingContainer);
}
- this._drawing = [];
};
@action
@@ -2032,7 +2036,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
icon: 'eye',
});
optionItems.push({
- description: (this._showDrawingEditor ? 'Close' : 'Show') + ' Drawing Editor',
+ description: 'Show Drawing Editor',
event: action(() => {
this._showDrawingEditor = !this._showDrawingEditor;
this._showDrawingEditor ? SmartDrawHandler.Instance.displayRegenerate(this._downX, this._downY - 10, this.createDrawing, this.removeDrawing) : SmartDrawHandler.Instance.hideRegenerate();
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
index f02cd9d45..b3fdd9379 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
@@ -3,6 +3,7 @@ import { IconButton } from 'browndash-components';
import { computed, makeObservable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
+import { Doc } from '../../../../fields/Doc';
import { unimplementedFunction } from '../../../../Utils';
import { SettingsManager } from '../../../util/SettingsManager';
import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu';
@@ -12,7 +13,7 @@ export class MarqueeOptionsMenu extends AntimodeMenu<AntimodeMenuProps> {
// eslint-disable-next-line no-use-before-define
static Instance: MarqueeOptionsMenu;
- public createCollection: (e: KeyboardEvent | React.PointerEvent | undefined, group?: boolean) => void = unimplementedFunction;
+ public createCollection: (e: KeyboardEvent | React.PointerEvent | undefined, group?: boolean, selection?: Doc[]) => Doc | void = unimplementedFunction;
public delete: (e: KeyboardEvent | React.PointerEvent | undefined) => void = unimplementedFunction;
public summarize: (e: KeyboardEvent | React.PointerEvent | undefined) => void = unimplementedFunction;
public showMarquee: () => void = unimplementedFunction;
diff --git a/src/client/views/smartdraw/AnnotationPalette.scss b/src/client/views/smartdraw/AnnotationPalette.scss
new file mode 100644
index 000000000..9f875f61a
--- /dev/null
+++ b/src/client/views/smartdraw/AnnotationPalette.scss
@@ -0,0 +1,10 @@
+.annotation-palette {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ position: absolute;
+ right: 14px;
+ top: 50px;
+ border-radius: 5px;
+ margin: auto;
+}
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>
+ );
+ }
+}
diff --git a/src/client/views/smartdraw/DrawingPalette.scss b/src/client/views/smartdraw/DrawingPalette.scss
deleted file mode 100644
index 0f1152b71..000000000
--- a/src/client/views/smartdraw/DrawingPalette.scss
+++ /dev/null
@@ -1,11 +0,0 @@
-.drawing-palette {
- display: grid;
- grid-template-columns: auto;
- position: absolute;
- right: 14px;
- width: 170px;
- height: 170px;
- top: 50px;
- border-radius: 5px;
- background-color: white;
-}
diff --git a/src/client/views/smartdraw/DrawingPalette.tsx b/src/client/views/smartdraw/DrawingPalette.tsx
deleted file mode 100644
index 87a39bc85..000000000
--- a/src/client/views/smartdraw/DrawingPalette.tsx
+++ /dev/null
@@ -1,89 +0,0 @@
-import { computed, makeObservable, observable } from 'mobx';
-import { observer } from 'mobx-react';
-import * as React from 'react';
-import { returnAll, returnFalse, returnOne, returnZero } from '../../../ClientUtils';
-import { Doc, StrListCast } from '../../../fields/Doc';
-import { emptyFunction } from '../../../Utils';
-import { CollectionViewType } from '../../documents/DocumentTypes';
-import { MarqueeView } from '../collections/collectionFreeForm';
-import { CollectionGridView } from '../collections/collectionGrid';
-import { CollectionStackingView } from '../collections/CollectionStackingView';
-import { DocumentView } from '../nodes/DocumentView';
-import { FieldViewProps } from '../nodes/FieldView';
-import { ObservableReactComponent } from '../ObservableReactComponent';
-import './DrawingPalette.scss';
-
-@observer
-export class DrawingPalette extends ObservableReactComponent<{}> {
- @observable private _savedDrawings: Doc[] = [];
- @observable _marqueeViewRef = React.createRef<MarqueeView>();
- private _stackRef = React.createRef<CollectionStackingView>();
-
- constructor(props: any) {
- super(props);
- makeObservable(this);
- }
-
- panelWidth = () => 100;
- panelHeight = () => 100;
-
- getCollection = () => {
- return this._marqueeViewRef.current?.collection(undefined, false, this._savedDrawings) || new Doc();
- };
-
- @computed get savedDrawingAnnos() {
- // const savedAnnos = Doc.MyDrawingAnnos;
- return (
- <div className="collectionMenu-contMenuButtons" style={{ height: '100%' }}>
- {/* <DocumentView PanelHeight={this.panelWidth} PanelWidth={this.panelHeight} Document={savedAnnos} renderDepth={2} isContentActive={returnFalse} childFilters={this.childFilters} /> */}
- {/* <CollectionStackingView
- {...this._props}
- Document={savedAnnos}
- // setContentViewBox={emptyFunction}
- // NativeWidth={returnZero}
- // NativeHeight={returnZero}
- ref={this._stackRef}
- PanelHeight={this.panelWidth}
- PanelWidth={this.panelHeight}
- // childFilters={this.childFilters}
- // sortFunc={this.sortByLinkAnchorY}
- // setHeight={this.setHeightCallback}
- // isAnnotationOverlay={false}
- // select={emptyFunction}
- NativeDimScaling={returnOne}
- // childlayout_showTitle={this.layout_showTitle}
- isContentActive={returnFalse}
- isSelected={returnFalse}
- isAnyChildContentActive={returnFalse}
- // childDocumentsActive={this._props.isContentActive}
- whenChildContentsActiveChanged={this._props.whenChildContentsActiveChanged}
- childHideDecorationTitle
- // ScreenToLocalTransform={this.screenToLocalTransform}
- renderDepth={this._props.renderDepth + 1}
- type_collection={CollectionViewType.Stacking}
- // fieldKey={'drawing-palette'}
- pointerEvents={returnAll}
- /> */}
- </div>
- );
- }
-
- render() {
- return (
- <div className="drawing-palette">
- {/* {this._savedDrawings.map(doc => {
- return <DocumentView
- Document={doc}
- renderDepth={0}
- PanelWidth={this.panelWidth}
- PanelHeight={this.panelHeight}
- isContentActive={this.isContentActive} />;
- })} */}
- {/* <CollectionGridView {...this._props} /> */}
- {}
- {/* <DocumentView Document={this.getCollection()} /> */}
- {this.savedDrawingAnnos}
- </div>
- );
- }
-}
diff --git a/src/client/views/smartdraw/SmartDrawHandler.scss b/src/client/views/smartdraw/SmartDrawHandler.scss
new file mode 100644
index 000000000..6d402a80f
--- /dev/null
+++ b/src/client/views/smartdraw/SmartDrawHandler.scss
@@ -0,0 +1,3 @@
+.smart-draw-handler {
+ position: absolute;
+}
diff --git a/src/client/views/smartdraw/SmartDrawHandler.tsx b/src/client/views/smartdraw/SmartDrawHandler.tsx
index d24cc9d50..24046bb83 100644
--- a/src/client/views/smartdraw/SmartDrawHandler.tsx
+++ b/src/client/views/smartdraw/SmartDrawHandler.tsx
@@ -7,15 +7,16 @@ import { ObservableReactComponent } from '../ObservableReactComponent';
import { Button, IconButton } from 'browndash-components';
import ReactLoading from 'react-loading';
import { AiOutlineSend } from 'react-icons/ai';
-// import './ImageLabelHandler.scss';
import { gptAPICall, GPTCallType } from '../../apis/gpt/GPT';
-import { InkData } from '../../../fields/InkField';
+import { InkData, InkTool } from '../../../fields/InkField';
import { SVGToBezier } from '../../util/bezierFit';
const { parse } = require('svgson');
import { Slider, Switch } from '@mui/material';
import { Doc } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
import { DocumentView } from '../nodes/DocumentView';
+import { BoolCast, NumCast, StrCast } from '../../../fields/Types';
+import './SmartDrawHandler.scss';
export interface DrawingOptions {
text: string;
@@ -43,7 +44,8 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
@observable private _size: number = 200;
@observable private _autoColor: boolean = true;
@observable private _regenInput: string = '';
- private _addFunc: (e: React.PointerEvent<Element>, strokeList: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => void = () => {};
+ @observable private _canInteract: boolean = true;
+ private _addFunc: (strokeList: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => void = () => {};
private _deleteFunc: (doc?: Doc) => void = () => {};
private _lastInput: DrawingOptions = { text: '', complexity: 5, size: 300, autoColor: true, x: 0, y: 0 };
private _lastResponse: string = '';
@@ -57,12 +59,12 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
@action
setUserInput = (input: string) => {
- this._userInput = input;
+ if (this._canInteract) this._userInput = input;
};
@action
setRegenInput = (input: string) => {
- this._regenInput = input;
+ if (this._canInteract) this._regenInput = input;
};
@action
@@ -72,21 +74,21 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
@action
setComplexity = (val: number) => {
- this._complexity = val;
+ if (this._canInteract) this._complexity = val;
};
@action
setSize = (val: number) => {
- this._size = val;
+ if (this._canInteract) this._size = val;
};
@action
setAutoColor = () => {
- this._autoColor = !this._autoColor;
+ if (this._canInteract) this._autoColor = !this._autoColor;
};
@action
- displaySmartDrawHandler = (x: number, y: number, addFunc: (e: React.PointerEvent<Element>, strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => void, deleteFunc: (doc?: Doc) => void) => {
+ displaySmartDrawHandler = (x: number, y: number, addFunc: (strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => void, deleteFunc: (doc?: Doc) => void) => {
this._pageX = x;
this._pageY = y;
this._display = true;
@@ -95,16 +97,18 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
};
@action
- displayRegenerate = (x: number, y: number, addFunc: (e: React.PointerEvent<Element>, strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => void, deleteFunc: (doc?: Doc) => void) => {
+ displayRegenerate = (x: number, y: number, addFunc: (strokeData: [InkData, string, string][], opts: DrawingOptions, gptRes: string, containerDoc?: Doc) => void, deleteFunc: (doc?: Doc) => void) => {
this._selectedDoc = DocumentView.SelectedDocs().lastElement();
const docData = this._selectedDoc[DocData];
this._addFunc = addFunc;
this._deleteFunc = deleteFunc;
this._pageX = x;
this._pageY = y;
+ this._display = false;
this._showRegenerate = true;
- this._lastResponse = docData.drawingData as string;
- this._lastInput = { text: docData.drawingInput as string, complexity: docData.drawingComplexity as number, size: docData.drawingSize as number, autoColor: docData.drawingColored as boolean, x: this._pageX, y: this._pageY };
+ this._showEditBox = false;
+ this._lastResponse = StrCast(docData.drawingData);
+ this._lastInput = { text: StrCast(docData.drawingInput), complexity: NumCast(docData.drawingComplexity), size: NumCast(docData.drawingSize), autoColor: BoolCast(docData.drawingColored), x: this._pageX, y: this._pageY };
};
@action
@@ -117,7 +121,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
this._complexity = 5;
this._size = 300;
this._autoColor = true;
- // this._regenInput = ''
+ Doc.ActiveTool = InkTool.None;
};
@action
@@ -127,12 +131,25 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
this._regenInput = '';
};
+ @action
+ handleKeyPress = async (event: React.KeyboardEvent) => {
+ if (event.key === 'Enter') {
+ if (this._showRegenerate) {
+ this.regenerate();
+ } else {
+ await this.drawWithGPT({ X: this._pageX, Y: this._pageY }, this._userInput);
+ this._userInput = '';
+ }
+ }
+ };
+
_errorOccurredOnce = false;
@action
- drawWithGPT = async (e: React.PointerEvent<Element>, input: string) => {
+ drawWithGPT = async (startPt: { X: number; Y: number }, input: string) => {
if (input === '') return;
- this._lastInput = { text: input, complexity: this._complexity, size: this._size, autoColor: this._autoColor, x: e.clientX, y: e.clientY };
+ this._lastInput = { text: input, complexity: this._complexity, size: this._size, autoColor: this._autoColor, x: startPt.X, y: startPt.Y };
this._isLoading = true;
+ this._canInteract = false;
this._showOptions = false;
try {
const res = await gptAPICall(`"${input}", "${this._complexity}", "${this._size}"`, GPTCallType.DRAW, undefined, true);
@@ -141,20 +158,22 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
return;
}
console.log(res);
- await this.parseResponse(e, res, { X: e.clientX, Y: e.clientY }, false);
+ const strokeData = await this.parseResponse(res, startPt, false);
this.hideSmartDrawHandler();
this._showRegenerate = true;
this._errorOccurredOnce = false;
+ this._isLoading = false;
+ this._canInteract = true;
+ return strokeData;
} catch (err) {
if (this._errorOccurredOnce) {
console.error('GPT call failed', err);
this._errorOccurredOnce = false;
} else {
this._errorOccurredOnce = true;
- this.drawWithGPT(e, input);
+ this.drawWithGPT(startPt, input);
}
}
- this._isLoading = false;
};
@action
@@ -163,14 +182,15 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
};
@action
- regenerate = async (e: React.PointerEvent<Element>) => {
+ regenerate = async () => {
this._isLoading = true;
+ this._canInteract = false;
try {
let res;
if (this._regenInput !== '') {
const prompt: string = `This is your previously generated svg code: ${this._lastResponse} for the user input "${this._lastInput.text}". Please regenerate it with the provided specifications.`;
res = await gptAPICall(`"${this._regenInput}"`, GPTCallType.DRAW, prompt, true);
- this._lastInput.text = `${this._lastInput.text} + ${this._regenInput}`;
+ this._lastInput.text = `${this._lastInput.text} ~~~ ${this._regenInput}`;
} else {
res = await gptAPICall(`"${this._lastInput.text}", "${this._lastInput.complexity}", "${this._lastInput.size}"`, GPTCallType.DRAW, undefined, true);
}
@@ -179,25 +199,26 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
return;
}
console.log(res);
- this.parseResponse(e, res, { X: this._lastInput.x, Y: this._lastInput.y }, true);
+ this.parseResponse(res, { X: this._lastInput.x, Y: this._lastInput.y }, true);
} catch (err) {
console.error('GPT call failed', err);
}
this._isLoading = false;
+ this._canInteract = true;
this._regenInput = '';
this._showEditBox = false;
};
@action
- parseResponse = async (e: React.PointerEvent<Element>, res: string, startPoint: { X: number; Y: number }, regenerate: boolean) => {
+ parseResponse = async (res: string, startPoint: { X: number; Y: number }, regenerate: boolean) => {
const svg = res.match(/<svg[^>]*>([\s\S]*?)<\/svg>/g);
+ console.log(svg);
console.log('start point is', startPoint);
if (svg) {
this._lastResponse = svg[0];
const svgObject = await parse(svg[0]);
const svgStrokes: any = svgObject.children;
const strokeData: [InkData, string, string][] = [];
- console.log('autocolor is', this._autoColor);
svgStrokes.forEach((child: any) => {
const convertedBezier: InkData = SVGToBezier(child.name, child.attributes);
strokeData.push([
@@ -210,10 +231,11 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
});
if (regenerate) {
this._deleteFunc(this._selectedDoc);
- this._addFunc(e, strokeData, this._lastInput, svg[0], this._selectedDoc);
+ this._addFunc(strokeData, this._lastInput, svg[0], this._selectedDoc);
} else {
- this._addFunc(e, strokeData, this._lastInput, svg[0]);
+ this._addFunc(strokeData, this._lastInput, svg[0]);
}
+ return { data: strokeData, lastInput: this._lastInput, lastRes: svg[0] };
}
};
@@ -222,7 +244,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
return (
<div
id="label-handler"
- className="contextMenu-cont"
+ className="smart-draw-handler"
style={{
display: this._display ? '' : 'none',
left: this._pageX,
@@ -242,8 +264,9 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
style={{ width: '19px' }}
/>
<input
- aria-label="label-input"
- id="new-label"
+ aria-label="Smart Draw Input"
+ className="smartdraw-input"
+ id="smartdraw-input"
type="text"
style={{ color: 'black' }}
value={this._userInput}
@@ -251,7 +274,9 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
this.setUserInput(e.target.value);
}}
placeholder="Enter item to draw"
+ onKeyDown={this.handleKeyPress}
/>
+ <IconButton tooltip="Advanced Options" icon={<FontAwesomeIcon icon={this._showOptions ? 'caret-down' : 'caret-right'} />} color={SettingsManager.userColor} style={{ width: '14px' }} onClick={this.setShowOptions} />
<Button
style={{ alignSelf: 'flex-end' }}
text="Send"
@@ -259,7 +284,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
iconPlacement="right"
color={SettingsManager.userColor}
onClick={e => {
- this.drawWithGPT(e as React.PointerEvent<Element>, this._userInput);
+ this.drawWithGPT({ X: e.clientX, Y: e.clientY }, this._userInput);
}}
/>
</div>
@@ -349,7 +374,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
return (
<div
id="smartdraw-options-menu"
- className="contextMenu-cont"
+ className="smart-draw-handler"
style={{
left: this._pageX,
...(this._yRelativeToTop ? { top: Math.max(0, this._pageY) } : { bottom: this._pageY }),
@@ -365,9 +390,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
tooltip="Regenerate"
icon={this._isLoading && this._regenInput === '' ? <ReactLoading type="spin" color={SettingsManager.userVariantColor} width={16} height={20} /> : <FontAwesomeIcon icon={'rotate'} />}
color={SettingsManager.userColor}
- onClick={e => {
- this.regenerate(e as React.PointerEvent<Element>);
- }}
+ onClick={this.regenerate}
/>
<IconButton tooltip="Edit with GPT" icon={<FontAwesomeIcon icon="pen-to-square" />} color={SettingsManager.userColor} onClick={this.edit} />
{this._showEditBox && (
@@ -378,6 +401,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
}}>
<input
aria-label="Edit instructions input"
+ className="smartdraw-input"
id="regen-input"
type="text"
style={{ color: 'black' }}
@@ -385,6 +409,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
onChange={e => {
this.setRegenInput(e.target.value);
}}
+ onKeyDown={this.handleKeyPress}
placeholder="Edit instructions"
/>
<Button
@@ -393,9 +418,7 @@ export class SmartDrawHandler extends ObservableReactComponent<{}> {
icon={this._isLoading && this._regenInput !== '' ? <ReactLoading type="spin" color={SettingsManager.userVariantColor} width={16} height={20} /> : <AiOutlineSend />}
iconPlacement="right"
color={SettingsManager.userColor}
- onClick={e => {
- this.regenerate(e as React.PointerEvent<Element>);
- }}
+ onClick={this.regenerate}
/>
</div>
)}
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index bc1abd26e..c86342870 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -276,7 +276,7 @@ export class Doc extends RefField {
public static get MyPublishedDocs() { return DocListCast(Doc.ActiveDashboard?.myPublishedDocs).concat(DocListCast(DocCast(Doc.UserDoc().myPublishedDocs)?.data)); } // prettier-ignore
public static get MyDashboards() { return DocCast(Doc.UserDoc().myDashboards); } // prettier-ignore
public static get MyTemplates() { return DocCast(Doc.UserDoc().myTemplates); } // prettier-ignore
- public static get MyDrawingAnnos() { return DocCast(Doc.UserDoc().myDrawingAnnos); } // prettier-ignore
+ public static get MyAnnos() { return DocCast(Doc.UserDoc().myAnnos); } // prettier-ignore
public static get MyImports() { return DocCast(Doc.UserDoc().myImports); } // prettier-ignore
public static get MyFilesystem() { return DocCast(Doc.UserDoc().myFilesystem); } // prettier-ignore
public static get MyTools() { return DocCast(Doc.UserDoc().myTools); } // prettier-ignore
@@ -1741,8 +1741,8 @@ ScriptingGlobals.add(function getEmbedding(doc: any) {
return Doc.MakeEmbedding(doc);
});
// eslint-disable-next-line prefer-arrow-callback
-ScriptingGlobals.add(function getCopy(doc: any, copyProto: any) {
- return doc.isTemplateDoc ? Doc.MakeDelegateWithProto(doc) : Doc.MakeCopy(doc, copyProto);
+ScriptingGlobals.add(async function getCopy(doc: any, copyProto: any) {
+ return doc.isTemplateDoc ? (doc.isGroup ? (await Doc.MakeClone(doc)).clone : Doc.MakeDelegateWithProto(doc)) : Doc.MakeCopy(doc, copyProto);
});
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function copyField(field: any) {