From 551ef2a117325faf90fd9f8087e9ffba39f7322e Mon Sep 17 00:00:00 2001
From: Zachary Zhang <zacharyzhang7@gmail.com>
Date: Thu, 6 Jun 2024 15:18:42 -0400
Subject: bug fixes

---
 src/client/views/nodes/DiagramBox.tsx | 54 ++++++++++++++++++++++++++++++-----
 1 file changed, 47 insertions(+), 7 deletions(-)

(limited to 'src/client/views/nodes/DiagramBox.tsx')

diff --git a/src/client/views/nodes/DiagramBox.tsx b/src/client/views/nodes/DiagramBox.tsx
index 32969fa53..cd58ef846 100644
--- a/src/client/views/nodes/DiagramBox.tsx
+++ b/src/client/views/nodes/DiagramBox.tsx
@@ -33,7 +33,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     @observable errorMessage = '';
     @observable mermaidCode = '';
 
-    @action handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+    @action handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
         this.inputValue = e.target.value;
     };
     async componentDidMount() {
@@ -41,9 +41,11 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         mermaid.initialize({
             securityLevel: 'loose',
             startOnLoad: true,
-            flowchart: { useMaxWidth: true, htmlLabels: true, curve: 'cardinal' },
+            darkMode: true,
+            flowchart: { useMaxWidth: false, htmlLabels: true, curve: 'cardinal' },
+            gantt: { barGap: 1 },
         });
-        this.mermaidCode = 'asdasdasd';
+        this.mermaidCode = 'a';
         const docArray: Doc[] = DocListCast(this.Document.data);
         let mermaidCodeDoc = docArray.filter(doc => doc.type === 'rich text');
         mermaidCodeDoc = mermaidCodeDoc.filter(doc => (doc.text as RichTextField).Text === 'mermaidCodeTitle');
@@ -68,12 +70,21 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             });
         }
         console.log(this.Document.title);
+        this.renderMermaidAsync(this.timeline);
         // this is so that ever time a new doc, text node or ink node, is created, this.createMermaidCode will run which will create a save
         reaction(
             () => DocListCast(this.Document.data),
             () => this.convertDrawingToMermaidCode(),
             { fireImmediately: true }
         );
+        reaction(
+            () =>
+                DocListCast(this.Document.data)
+                    .filter(doc => doc.type === 'rich text')
+                    .map(doc => (doc.text as RichTextField).Text),
+            () => this.convertDrawingToMermaidCode(),
+            { fireImmediately: true }
+        );
     }
     renderMermaid = async (str: string) => {
         try {
@@ -101,6 +112,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         }
     }
     @action handleRenderClick = () => {
+        this.mermaidCode = '';
         this.generateMermaidCode();
     };
     @action async generateMermaidCode() {
@@ -261,13 +273,41 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         }
         return false;
     };
-
+    autoResize(element: HTMLTextAreaElement): void {
+        element.style.height = '5px';
+        element.style.height = element.scrollHeight + 'px';
+    }
+    timeline = `gantt
+    title College Timeline
+    dateFormat  YYYY-MM-DD
+    section Semester 1
+    Orientation           :done,    des1, 2023-08-01, 2023-08-03
+    Classes Start         :active,  des2, 2023-08-04, 2023-12-15
+    Midterm Exams         :         des3, 2023-10-15, 2023-10-20
+    End of Semester       :         des4, 2023-12-16, 2023-12-20
+    section Semester 2
+    Classes Start         :         des5, 2024-01-10, 2024-05-15
+    Spring Break          :         des6, 2024-03-15, 2024-03-22
+    Midterm Exams         :         des7, 2024-03-25, 2024-03-30
+    Final Exams           :         des8, 2024-05-10, 2024-05-15
+    section Summer Break
+    Internship            :         des9, 2024-06-01, 2024-08-31
+    section Semester 3
+    Classes Start         :         des10, 2024-09-01, 2025-12-15
+    Midterm Exams         :         des11, 2024-11-15, 2024-11-20
+    End of Semester       :         des12, 2025-12-16, 2025-12-20
+    section Semester 4
+    Classes Start         :         des13, 2025-01-10, 2025-05-15
+    Spring Break          :         des14, 2025-03-15, 2025-03-22
+    Midterm Exams         :         des15, 2025-03-25, 2025-03-30
+    Final Exams           :         des16, 2025-05-10, 2025-05-15
+    Graduation            :         des17, 2025-05-20, 2025-05-21`;
     render() {
         return (
-            <div ref={this._ref} className="DIYNodeBox">
-                <div ref={this._dragRef} className="DIYNodeBox-wrapper">
+            <div ref={this._ref} className="DiagramBox">
+                <div ref={this._dragRef} className="DiagramBox-wrapper">
                     <div className="search-bar">
-                        <input type="text" value={this.inputValue} onChange={this.handleInputChange} />
+                        <textarea value={this.inputValue} onChange={this.handleInputChange} onInput={e => this.autoResize(e.target as HTMLTextAreaElement)} />
                         <button type="button" onClick={this.handleRenderClick}>
                             Generate
                         </button>
-- 
cgit v1.2.3-70-g09d2


From 6cce041a907ba2c4721a9202218169d3f5db09c2 Mon Sep 17 00:00:00 2001
From: Zachary Zhang <zacharyzhang7@gmail.com>
Date: Fri, 7 Jun 2024 12:18:03 -0400
Subject: fix squished timeline diagram

---
 src/client/views/nodes/DiagramBox.scss | 13 -------------
 src/client/views/nodes/DiagramBox.tsx  |  4 ++--
 2 files changed, 2 insertions(+), 15 deletions(-)

(limited to 'src/client/views/nodes/DiagramBox.tsx')

diff --git a/src/client/views/nodes/DiagramBox.scss b/src/client/views/nodes/DiagramBox.scss
index 58a98cc59..b3d50a4bd 100644
--- a/src/client/views/nodes/DiagramBox.scss
+++ b/src/client/views/nodes/DiagramBox.scss
@@ -13,17 +13,6 @@
         flex-direction: column;
         align-items: center;
         justify-content: center;
-        .DIYNodeBox {
-            /* existing code */
-
-            .DIYNodeBox-iframe {
-                height: 100%;
-                width: 100%;
-                border: none;
-
-            }
-        }
-
         .search-bar {
             display: flex;
             flex-wrap: wrap;
@@ -62,8 +51,6 @@
                 display: flex;
                 justify-content: center;
                 align-items: center;
-                width:100%;
-                height:100%; 
                 svg{
                     max-width: none !important;
                 }
diff --git a/src/client/views/nodes/DiagramBox.tsx b/src/client/views/nodes/DiagramBox.tsx
index cd58ef846..af4410394 100644
--- a/src/client/views/nodes/DiagramBox.tsx
+++ b/src/client/views/nodes/DiagramBox.tsx
@@ -43,7 +43,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             startOnLoad: true,
             darkMode: true,
             flowchart: { useMaxWidth: false, htmlLabels: true, curve: 'cardinal' },
-            gantt: { barGap: 1 },
+            gantt: { useMaxWidth: true, useWidth: 2000 },
         });
         this.mermaidCode = 'a';
         const docArray: Doc[] = DocListCast(this.Document.data);
@@ -327,5 +327,5 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
 
 Docs.Prototypes.TemplateMap.set(DocumentType.DIAGRAM, {
     layout: { view: DiagramBox, dataField: 'dadta' },
-    options: { _height: 300, _layout_fitWidth: true, _layout_nativeDimEditable: true, _layout_reflowVertical: true, waitForDoubleClickToClick: 'always', systemIcon: 'BsGlobe' },
+    options: { _height: 300, _layout_fitWidth: false, _layout_nativeDimEditable: true, _layout_reflowVertical: true, waitForDoubleClickToClick: 'always', _layout_reflowHorizontal: true, systemIcon: 'BsGlobe' },
 });
-- 
cgit v1.2.3-70-g09d2


From 1d9a9f05acc1bae66b65f73246741d17f7a51186 Mon Sep 17 00:00:00 2001
From: Zachary Zhang <zacharyzhang7@gmail.com>
Date: Mon, 10 Jun 2024 15:01:05 -0400
Subject: draft of ui update

---
 src/client/util/CurrentUserUtils.ts    |   2 +-
 src/client/views/nodes/DiagramBox.scss |  32 +++++-
 src/client/views/nodes/DiagramBox.tsx  | 198 +++++++++++++++++++++------------
 3 files changed, 156 insertions(+), 76 deletions(-)

(limited to 'src/client/views/nodes/DiagramBox.tsx')

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index e095bc659..8ece897f4 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -398,7 +398,7 @@ pie title Minerals in my tap water
             { toolTip: "Tap or drag to create a plotly node",     title: "Plotly", icon: "rocket",      dragFactory: doc.emptyPlotly as Doc,     clickFactory: DocCast(doc.emptyMermaids)}, 
             { toolTip: "Tap or drag to create a physics simulation",title: "Simulation", icon: "rocket",dragFactory: doc.emptySimulation as Doc, clickFactory: DocCast(doc.emptySimulation), funcs: { hidden: "IsNoviceMode()"}}, 
             { toolTip: "Tap or drag to create a note board",      title: "Notes", icon: "book",         dragFactory: doc.emptyNoteboard as Doc,  clickFactory: DocCast(doc.emptyNoteboard)},
-            { toolTip: "Tap or drag to create an iamge",          title: "Image", icon: "image",        dragFactory: doc.emptyImage as Doc,      clickFactory: DocCast(doc.emptyImage)},
+            { toolTip: "Tap or drag to create an image",          title: "Image", icon: "image",        dragFactory: doc.emptyImage as Doc,      clickFactory: DocCast(doc.emptyImage)},
             { toolTip: "Tap or drag to create a collection",      title: "Col", icon: "folder",         dragFactory: doc.emptyCollection as Doc, clickFactory: DocCast(doc.emptyTab)},
             { toolTip: "Tap or drag to create a webpage",         title: "Web", icon: "globe-asia",     dragFactory: doc.emptyWebpage as Doc,    clickFactory: DocCast(doc.emptyWebpage)},
             { toolTip: "Tap or drag to create a comparison box",  title: "Compare", icon: "columns",    dragFactory: doc.emptyComparison as Doc, clickFactory: DocCast(doc.emptyComparison)},
diff --git a/src/client/views/nodes/DiagramBox.scss b/src/client/views/nodes/DiagramBox.scss
index b3d50a4bd..64b0e6c0e 100644
--- a/src/client/views/nodes/DiagramBox.scss
+++ b/src/client/views/nodes/DiagramBox.scss
@@ -3,9 +3,27 @@
     height: 100%;
     display: flex;
     flex-direction: column;
-    align-items: center;
-    justify-content: center;
-
+    .buttonCollections{
+        display: flex;
+        justify-content: center;
+        flex-direction: column;
+        height:100%;
+        button{
+            font-size:10px;
+            margin:5px;
+            height:100%;
+            width:30%;
+            border: none;
+            border-radius: 5px;
+            cursor: pointer;
+            background-color: #007bff;
+            color: #fff;
+            transition: background-color 0.3s ease;
+        }
+        button:hover {
+            background-color: #0056b3;
+        }
+    }
     .DiagramBox-wrapper {
         width: 100%;
         height: 100%;
@@ -13,6 +31,11 @@
         flex-direction: column;
         align-items: center;
         justify-content: center;
+        .backButton{
+            position: absolute;
+            top:0;
+            left:0;
+        }
         .search-bar {
             display: flex;
             flex-wrap: wrap;
@@ -23,10 +46,9 @@
 
             textarea {
                 flex: 1;
-                height:5px;
+                height: 5px;
                 margin-right: 10px;
                 min-height: 20px;
-                height:auto;
                 resize:none;
                 overflow: hidden;
             }
diff --git a/src/client/views/nodes/DiagramBox.tsx b/src/client/views/nodes/DiagramBox.tsx
index af4410394..a294ed75c 100644
--- a/src/client/views/nodes/DiagramBox.tsx
+++ b/src/client/views/nodes/DiagramBox.tsx
@@ -1,3 +1,4 @@
+/* eslint-disable jsx-a11y/control-has-associated-label */
 import mermaid from 'mermaid';
 import { action, makeObservable, observable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
@@ -5,7 +6,7 @@ import * as React from 'react';
 import { Doc, DocListCast } from '../../../fields/Doc';
 import { List } from '../../../fields/List';
 import { RichTextField } from '../../../fields/RichTextField';
-import { DocCast, NumCast } from '../../../fields/Types';
+import { DocCast } from '../../../fields/Types';
 import { GPTCallType, gptAPICall } from '../../apis/gpt/GPT';
 import { DocumentType } from '../../documents/DocumentTypes';
 import { Docs } from '../../documents/Documents';
@@ -16,6 +17,14 @@ import { InkingStroke } from '../InkingStroke';
 import './DiagramBox.scss';
 import { FieldView, FieldViewProps } from './FieldView';
 
+enum menuState {
+    option,
+    mermaidCode,
+    drawing,
+    gpt,
+    justCreated,
+}
+
 @observer
 export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     public static LayoutString(fieldKey: string) {
@@ -27,7 +36,8 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         super(props);
         makeObservable(this);
     }
-
+    @observable menuState = menuState.justCreated;
+    @observable renderDiv: React.ReactNode;
     @observable inputValue = '';
     @observable loading = false;
     @observable errorMessage = '';
@@ -46,31 +56,11 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             gantt: { useMaxWidth: true, useWidth: 2000 },
         });
         this.mermaidCode = 'a';
-        const docArray: Doc[] = DocListCast(this.Document.data);
-        let mermaidCodeDoc = docArray.filter(doc => doc.type === 'rich text');
-        mermaidCodeDoc = mermaidCodeDoc.filter(doc => (doc.text as RichTextField).Text === 'mermaidCodeTitle');
-        if (mermaidCodeDoc[0]) {
-            if (typeof mermaidCodeDoc[0].title === 'string') {
-                console.log(mermaidCodeDoc[0].title);
-                if (mermaidCodeDoc[0].title !== '') {
-                    this.renderMermaidAsync(mermaidCodeDoc[0].title);
-                }
-            }
-        }
-        // this will create a text doc far away where the user cant to save the mermaid code, where it will then be accessed when flipped to the diagram box side
-        // the code is stored in the title since it is much easier to change than in the text
-        else {
-            DocumentManager.Instance.AddViewRenderedCb(this.Document, docViewForYourCollection => {
-                if (docViewForYourCollection && docViewForYourCollection.ComponentView) {
-                    if (docViewForYourCollection.ComponentView.addDocument && docViewForYourCollection.ComponentView.removeDocument) {
-                        const newDoc = Docs.Create.TextDocument('mermaidCodeTitle', { title: '', x: 9999 + NumCast(this.layoutDoc._width), y: 9999 });
-                        docViewForYourCollection.ComponentView?.addDocument(newDoc);
-                    }
-                }
-            });
+        if (typeof this.Document.mermaidCode === 'string') {
+            this.renderMermaidAsync(this.Document.mermaidCode);
         }
         console.log(this.Document.title);
-        this.renderMermaidAsync(this.timeline);
+        // this.renderMermaidAsync(this.timeline);
         // this is so that ever time a new doc, text node or ink node, is created, this.createMermaidCode will run which will create a save
         reaction(
             () => DocListCast(this.Document.data),
@@ -86,6 +76,31 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             { fireImmediately: true }
         );
     }
+    componentDidUpdate = () => {
+        if (typeof this.Document.mermaidCode === 'string' && this.Document.menuState === 'drawing') {
+            this.renderMermaidAsync(this.Document.mermaidCode);
+        }
+    };
+    switchRenderDiv() {
+        switch (this.Document.menuState) {
+            case 'option':
+                this.renderDiv = this.renderOption();
+                break;
+            case 'drawing':
+                this.renderDiv = this.renderDrawing();
+                break;
+            case 'gpt':
+                this.renderDiv = this.renderGpt();
+                break;
+            case 'mermaidCode':
+                this.renderDiv = this.renderMermaidCode();
+                break;
+            default:
+                this.menuState = menuState.option;
+                this.renderDiv = this.renderOption();
+                console.log(this.renderDiv);
+        }
+    }
     renderMermaid = async (str: string) => {
         try {
             const { svg, bindFunctions } = await this.mermaidDiagram(str);
@@ -119,20 +134,6 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         console.log('Generating Mermaid Code');
         this.loading = true;
         let prompt = '';
-        // let docArray: Doc[] = DocListCast(this.Document.data);
-        // let mermaidCodeDoc = docArray.filter(doc => doc.type == 'rich text')
-        // mermaidCodeDoc=mermaidCodeDoc.filter(doc=>(doc.text as RichTextField).Text=='mermaidCodeTitle')
-        // if(mermaidCodeDoc[0]){
-        //     console.log(mermaidCodeDoc[0].title)
-        //     if(typeof mermaidCodeDoc[0].title=='string'){
-        //         console.log(mermaidCodeDoc[0].title)
-        //         if(mermaidCodeDoc[0].title!=""){
-        //             prompt="Edit this code "+this.inputValue+": "+mermaidCodeDoc[0].title
-        //             console.log("you have to see me")
-        //         }
-        //     }
-        // }
-        // else{
         prompt = 'Write this in mermaid code and only give me the mermaid code: ' + this.inputValue;
         console.log('there is no text save');
         // }
@@ -222,22 +223,11 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                     }
                 }
                 // this will save the text
-                DocumentManager.Instance.AddViewRenderedCb(this.Document, docViewForYourCollection => {
-                    if (docViewForYourCollection && docViewForYourCollection.ComponentView) {
-                        if (docViewForYourCollection.ComponentView.addDocument && docViewForYourCollection.ComponentView.removeDocument) {
-                            let docs: Doc[] = DocListCast(this.Document.data);
-                            docs = docs.filter(doc => doc.type === 'rich text');
-                            const mermaidCodeDoc = docs.filter(doc => (doc.text as RichTextField).Text === 'mermaidCodeTitle');
-                            if (mermaidCodeDoc[0]) {
-                                if (diagramExists) {
-                                    mermaidCodeDoc[0].title = mermaidCode;
-                                } else {
-                                    mermaidCodeDoc[0].title = '';
-                                }
-                            }
-                        }
-                    }
-                });
+                if (diagramExists) {
+                    this.Document.mermaidCode = mermaidCode;
+                } else {
+                    this.Document.mermaidCode = '';
+                }
             }
         }
     }
@@ -277,6 +267,87 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         element.style.height = '5px';
         element.style.height = element.scrollHeight + 'px';
     }
+    drawingButton = () => {
+        this.Document.menuState = 'drawing';
+    };
+    gptButton = () => {
+        this.Document.menuState = 'gpt';
+    };
+    mermaidButton = () => {
+        this.Document.menuState = 'mermaidCode';
+    };
+    optionButton = () => {
+        this.Document.menuState = 'option';
+    };
+    renderOption(): React.ReactNode {
+        return (
+            <div className="buttonCollections">
+                <button type="button" onClick={this.drawingButton}>
+                    Drawing
+                </button>
+                <button type="button" onClick={this.gptButton}>
+                    GPT
+                </button>
+                <button type="button" onClick={this.mermaidButton}>
+                    Mermaid Code
+                </button>
+            </div>
+        );
+    }
+    renderDrawing (): React.ReactNode {
+        return (
+            <div ref={this._dragRef} className="DiagramBox-wrapper">
+                <button type="button" className="backButton" onClick={this.optionButton}>
+                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
+                        <path d="M0 0h24v24H0z" fill="none" />
+                        <path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" />
+                    </svg>
+                </button>
+                <div className="content">
+                    <div id={'dashDiv' + this.Document.title} className="diagramBox" />
+                </div>
+            </div>
+        );
+    }
+
+    renderGpt(): React.ReactNode {
+        return (
+            <div ref={this._dragRef} className="DiagramBox-wrapper">
+                <button type="button" className="backButton" onClick={this.optionButton}>
+                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
+                        <path d="M0 0h24v24H0z" fill="none" />
+                        <path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" />
+                    </svg>
+                </button>
+                <div className="search-bar">
+                    <textarea value={this.inputValue} onChange={this.handleInputChange} onInput={e => this.autoResize(e.target as HTMLTextAreaElement)} />
+                    <button type="button" onClick={this.handleRenderClick}>
+                        Generate
+                    </button>
+                </div>
+                <div className="content">
+                    {this.mermaidCode ? (
+                        <div id={'dashDiv' + this.Document.title} className="diagramBox" />
+                    ) : (
+                        <div>{this.loading ? <div className="loading-circle" /> : <div>{this.errorMessage ? this.errorMessage : 'Insert prompt to generate diagram'}</div>}</div>
+                    )}
+                </div>
+            </div>
+        );
+    }
+
+    renderMermaidCode(): React.ReactNode {
+        return (
+            <div ref={this._dragRef} className="DiagramBox-wrapper">
+                <button className="backButton" type="button" onClick={this.optionButton}>
+                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
+                        <path d="M0 0h24v24H0z" fill="none" />
+                        <path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" />
+                    </svg>
+                </button>
+            </div>
+        );
+    }
     timeline = `gantt
     title College Timeline
     dateFormat  YYYY-MM-DD
@@ -303,23 +374,10 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     Final Exams           :         des16, 2025-05-10, 2025-05-15
     Graduation            :         des17, 2025-05-20, 2025-05-21`;
     render() {
+        this.switchRenderDiv();
         return (
             <div ref={this._ref} className="DiagramBox">
-                <div ref={this._dragRef} className="DiagramBox-wrapper">
-                    <div className="search-bar">
-                        <textarea value={this.inputValue} onChange={this.handleInputChange} onInput={e => this.autoResize(e.target as HTMLTextAreaElement)} />
-                        <button type="button" onClick={this.handleRenderClick}>
-                            Generate
-                        </button>
-                    </div>
-                    <div className="content">
-                        {this.mermaidCode ? (
-                            <div id={'dashDiv' + this.Document.title} className="diagramBox" />
-                        ) : (
-                            <div>{this.loading ? <div className="loading-circle" /> : <div>{this.errorMessage ? this.errorMessage : 'Insert prompt to generate diagram'}</div>}</div>
-                        )}
-                    </div>
-                </div>
+                {this.renderDiv}
             </div>
         );
     }
-- 
cgit v1.2.3-70-g09d2


From ee558136b1cd4b60736b2b48ec7b569b526e31ec Mon Sep 17 00:00:00 2001
From: Zachary Zhang <zacharyzhang7@gmail.com>
Date: Wed, 12 Jun 2024 10:57:27 -0400
Subject: ui bug fixes

---
 src/client/views/nodes/DiagramBox.scss | 128 ++++++++++++++++++---------------
 src/client/views/nodes/DiagramBox.tsx  |  96 ++++++++++++++-----------
 2 files changed, 127 insertions(+), 97 deletions(-)

(limited to 'src/client/views/nodes/DiagramBox.tsx')

diff --git a/src/client/views/nodes/DiagramBox.scss b/src/client/views/nodes/DiagramBox.scss
index 64b0e6c0e..1b6efe01d 100644
--- a/src/client/views/nodes/DiagramBox.scss
+++ b/src/client/views/nodes/DiagramBox.scss
@@ -8,11 +8,12 @@
         justify-content: center;
         flex-direction: column;
         height:100%;
+        padding:20px;
+        padding-right:40px;
         button{
-            font-size:10px;
-            margin:5px;
+            font-size:15px;
             height:100%;
-            width:30%;
+            width:100%;
             border: none;
             border-radius: 5px;
             cursor: pointer;
@@ -23,6 +24,7 @@
         button:hover {
             background-color: #0056b3;
         }
+        
     }
     .DiagramBox-wrapper {
         width: 100%;
@@ -31,43 +33,58 @@
         flex-direction: column;
         align-items: center;
         justify-content: center;
-        .backButton{
-            position: absolute;
-            top:0;
-            left:0;
-        }
-        .search-bar {
-            display: flex;
-            flex-wrap: wrap;
-            justify-content: center;
-            align-items: center;
-            width: 100%;
-            padding: 10px;
-
-            textarea {
-                flex: 1;
-                height: 5px;
-                margin-right: 10px;
-                min-height: 20px;
-                resize:none;
-                overflow: hidden;
-            }
-
-            button {
-                padding: 5px 10px;
-                width:80px;
-                height:30px;
-                border-radius: 10px;
-            }
-        }
-
         .content {
-            flex: 1;
             display: flex;
             justify-content: center;
             align-items: center;
+            flex-direction: column;
+            padding:10px;
             width:100%;
             height:100%;
+            .topbar{
+                .backButtonDrawing{
+                    padding: 5px 10px;
+                    height:23px;
+                    border-radius: 10px;
+                    text-align: center;
+                    padding:0;
+                    width:50px;
+                    font-size:10px;
+                    position:absolute;
+                    top:10px;
+                    left:10px;
+                }
+                p{
+                    margin-left:60px
+                }
+            }
+            .search-bar {
+                .backButton{
+                    text-align: center;
+                    padding:0;
+                    width:50px;
+                    font-size:10px;
+
+                }
+                display: flex;
+                flex-wrap: wrap;
+                justify-content: center;
+                align-items: center;
+                width: 100%;
+                textarea {
+                    flex: 1;
+                    height: 5px;
+                    min-height: 20px;
+                    resize:none;
+                    overflow: hidden;
+                }
+                button {
+                    padding: 5px 10px;
+                    width:80px;
+                    height:23px;
+                    border-radius: 10px;
+                }
+            }
             .diagramBox{
                 flex: 1;
                 display: flex;
@@ -76,28 +93,27 @@
                 svg{
                     max-width: none !important;
                 }
-            }
-        }
-
-        .loading-circle {
-            position: absolute;
-            display:flex;
-            align-items: center;
-            justify-content: center;
-            width: 50px;
-            height: 50px;
-            border-radius: 50%;
-            border: 3px solid #ccc;
-            border-top-color: #333;
-            animation: spin 1s infinite linear;
-        }
-
-        @keyframes spin {
-            0% {
-                transform: rotate(0deg);
-            }
-            100% {
-                transform: rotate(360deg);
+                .loading-circle {
+                    position: absolute;
+                    display:flex;
+                    align-items: center;
+                    justify-content: center;
+                    width: 50px;
+                    height: 50px;
+                    border-radius: 50%;
+                    border: 3px solid #ccc;
+                    border-top-color: #333;
+                    animation: spin 1s infinite linear;
+                }
+        
+                @keyframes spin {
+                    0% {
+                        transform: rotate(0deg);
+                    }
+                    100% {
+                        transform: rotate(360deg);
+                    }
+                }
             }
         }
     }
diff --git a/src/client/views/nodes/DiagramBox.tsx b/src/client/views/nodes/DiagramBox.tsx
index a294ed75c..220c43ead 100644
--- a/src/client/views/nodes/DiagramBox.tsx
+++ b/src/client/views/nodes/DiagramBox.tsx
@@ -45,6 +45,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
 
     @action handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
         this.inputValue = e.target.value;
+        console.log(e.target.value);
     };
     async componentDidMount() {
         this._props.setContentViewBox?.(this);
@@ -55,9 +56,14 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             flowchart: { useMaxWidth: false, htmlLabels: true, curve: 'cardinal' },
             gantt: { useMaxWidth: true, useWidth: 2000 },
         });
+        if (!this.Document.testValue) {
+            this.Document.height = 500;
+            this.Document.width = 500;
+        }
+        this.Document.testValue = 'a';
         this.mermaidCode = 'a';
-        if (typeof this.Document.mermaidCode === 'string') {
-            this.renderMermaidAsync(this.Document.mermaidCode);
+        if (typeof this.Document.drawingMermaidCode === 'string' && this.Document.menuState === 'drawing') {
+            this.renderMermaidAsync(this.Document.drawingMermaidCode);
         }
         console.log(this.Document.title);
         // this.renderMermaidAsync(this.timeline);
@@ -77,8 +83,11 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         );
     }
     componentDidUpdate = () => {
-        if (typeof this.Document.mermaidCode === 'string' && this.Document.menuState === 'drawing') {
-            this.renderMermaidAsync(this.Document.mermaidCode);
+        if (typeof this.Document.drawingMermaidCode === 'string' && this.Document.menuState === 'drawing') {
+            this.renderMermaidAsync(this.Document.drawingMermaidCode);
+        }
+        if (typeof this.Document.gptMermaidCode === 'string' && this.Document.menuState === 'gpt') {
+            this.renderMermaidAsync(this.Document.gptMermaidCode);
         }
     };
     switchRenderDiv() {
@@ -128,7 +137,9 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     }
     @action handleRenderClick = () => {
         this.mermaidCode = '';
-        this.generateMermaidCode();
+        if (this.inputValue) {
+            this.generateMermaidCode();
+        }
     };
     @action async generateMermaidCode() {
         console.log('Generating Mermaid Code');
@@ -155,6 +166,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             }
         }
         this.renderMermaidAsync.call(this, this.removeWords(this.mermaidCode));
+        this.Document.gptMermaidCode = this.removeWords(this.mermaidCode);
         this.loading = false;
     }
     isValidCode = (html: string) => true;
@@ -224,9 +236,9 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                 }
                 // this will save the text
                 if (diagramExists) {
-                    this.Document.mermaidCode = mermaidCode;
+                    this.Document.drawingMermaidCode = mermaidCode;
                 } else {
-                    this.Document.mermaidCode = '';
+                    this.Document.drawingMermaidCode = '';
                 }
             }
         }
@@ -283,27 +295,28 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         return (
             <div className="buttonCollections">
                 <button type="button" onClick={this.drawingButton}>
-                    Drawing
+                    Drawing - Create diagram from ink drawing
                 </button>
                 <button type="button" onClick={this.gptButton}>
-                    GPT
+                    GPT - Generate diagram with AI prompt
                 </button>
                 <button type="button" onClick={this.mermaidButton}>
-                    Mermaid Code
+                    Mermaid Editor - Create diagram with mermaid code
                 </button>
             </div>
         );
     }
-    renderDrawing (): React.ReactNode {
+    renderDrawing(): React.ReactNode {
+        console.log(this.Document.mermaidCode);
         return (
             <div ref={this._dragRef} className="DiagramBox-wrapper">
-                <button type="button" className="backButton" onClick={this.optionButton}>
-                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
-                        <path d="M0 0h24v24H0z" fill="none" />
-                        <path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" />
-                    </svg>
-                </button>
                 <div className="content">
+                    <div className="topBar">
+                        <button className="backButtonDrawing" type="button" onClick={this.optionButton}>
+                            Back
+                        </button>
+                        {!this.Document.mermaidCode && <p>Click the red pen icon to flip onto the collection side and draw a diagram with ink</p>}
+                    </div>
                     <div id={'dashDiv' + this.Document.title} className="diagramBox" />
                 </div>
             </div>
@@ -313,24 +326,17 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     renderGpt(): React.ReactNode {
         return (
             <div ref={this._dragRef} className="DiagramBox-wrapper">
-                <button type="button" className="backButton" onClick={this.optionButton}>
-                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
-                        <path d="M0 0h24v24H0z" fill="none" />
-                        <path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" />
-                    </svg>
-                </button>
-                <div className="search-bar">
-                    <textarea value={this.inputValue} onChange={this.handleInputChange} onInput={e => this.autoResize(e.target as HTMLTextAreaElement)} />
-                    <button type="button" onClick={this.handleRenderClick}>
-                        Generate
-                    </button>
-                </div>
                 <div className="content">
-                    {this.mermaidCode ? (
-                        <div id={'dashDiv' + this.Document.title} className="diagramBox" />
-                    ) : (
-                        <div>{this.loading ? <div className="loading-circle" /> : <div>{this.errorMessage ? this.errorMessage : 'Insert prompt to generate diagram'}</div>}</div>
-                    )}
+                    <div className="search-bar">
+                        <button className="backButton" type="button" onClick={this.optionButton}>
+                            Back
+                        </button>
+                        <textarea value={this.inputValue} placeholder="Enter GPT prompt" onChange={this.handleInputChange} onInput={e => this.autoResize(e.target as HTMLTextAreaElement)} />
+                        <button className="generateButton" type="button" onClick={this.handleRenderClick}>
+                            Generate
+                        </button>
+                    </div>
+                    <div id={'dashDiv' + this.Document.title} className="diagramBox" />
                 </div>
             </div>
         );
@@ -339,15 +345,23 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     renderMermaidCode(): React.ReactNode {
         return (
             <div ref={this._dragRef} className="DiagramBox-wrapper">
-                <button className="backButton" type="button" onClick={this.optionButton}>
-                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
-                        <path d="M0 0h24v24H0z" fill="none" />
-                        <path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" />
-                    </svg>
-                </button>
+                <div className="content">
+                    <div className="search-bar">
+                        <button className="backButton" type="button" onClick={this.optionButton}>
+                            Back
+                        </button>
+                        <textarea placeholder="Enter Mermaid Code" onChange={this.handleInputChangeEditor} onInput={e => this.autoResize(e.target as HTMLTextAreaElement)} />
+                    </div>
+                    <div id={'dashDiv' + this.Document.title} className="diagramBox" />
+                </div>
             </div>
         );
     }
+    handleInputChangeEditor = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
+        if (typeof e.target.value === 'string') {
+            this.renderMermaidAsync(e.target.value);
+        }
+    };
     timeline = `gantt
     title College Timeline
     dateFormat  YYYY-MM-DD
@@ -385,5 +399,5 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
 
 Docs.Prototypes.TemplateMap.set(DocumentType.DIAGRAM, {
     layout: { view: DiagramBox, dataField: 'dadta' },
-    options: { _height: 300, _layout_fitWidth: false, _layout_nativeDimEditable: true, _layout_reflowVertical: true, waitForDoubleClickToClick: 'always', _layout_reflowHorizontal: true, systemIcon: 'BsGlobe' },
+    options: { _height: 700, _width: 700, _layout_fitWidth: false, _layout_nativeDimEditable: true, _layout_reflowVertical: true, waitForDoubleClickToClick: 'always', _layout_reflowHorizontal: true, systemIcon: 'BsGlobe' },
 });
-- 
cgit v1.2.3-70-g09d2


From cfe7b6275b0c0e9184665d4d28d467b071e2d705 Mon Sep 17 00:00:00 2001
From: Zachary Zhang <zacharyzhang7@gmail.com>
Date: Thu, 13 Jun 2024 12:40:54 -0400
Subject: fix bug with auto resize

---
 src/client/views/nodes/DiagramBox.scss |  50 ++++++-----
 src/client/views/nodes/DiagramBox.tsx  | 154 +++++++++++++++++++++++++++++++--
 2 files changed, 176 insertions(+), 28 deletions(-)

(limited to 'src/client/views/nodes/DiagramBox.tsx')

diff --git a/src/client/views/nodes/DiagramBox.scss b/src/client/views/nodes/DiagramBox.scss
index 1b6efe01d..5b12c6f89 100644
--- a/src/client/views/nodes/DiagramBox.scss
+++ b/src/client/views/nodes/DiagramBox.scss
@@ -1,4 +1,5 @@
 .DiagramBox {
+    overflow:hidden;
     width: 100%;
     height: 100%;
     display: flex;
@@ -27,6 +28,7 @@
         
     }
     .DiagramBox-wrapper {
+        overflow:hidden;
         width: 100%;
         height: 100%;
         display: flex;
@@ -34,6 +36,7 @@
         align-items: center;
         justify-content: center;
         .content {
+            overflow: hidden;
             display: flex;
             justify-content: center;
             align-items: center;
@@ -59,6 +62,9 @@
                 }
             }
             .search-bar {
+                overflow:hidden;
+                position:absolute;
+                top:0;
                 .backButton{
                     text-align: center;
                     padding:0;
@@ -85,34 +91,36 @@
                     border-radius: 10px;
                 }
             }
+            .loading-circle {
+                position: absolute;
+                display:flex;
+                align-items: center;
+                justify-content: center;
+                width: 50px;
+                height: 50px;
+                border-radius: 50%;
+                border: 3px solid #ccc;
+                border-top-color: #333;
+                animation: spin 1s infinite linear;
+            }
+            @keyframes spin {
+                0% {
+                    transform: rotate(0deg);
+                }
+                100% {
+                    transform: rotate(360deg);
+                }
+            }
             .diagramBox{
                 flex: 1;
                 display: flex;
                 justify-content: center;
                 align-items: center;
                 svg{
+                    position: relative;
+                    top:25;
                     max-width: none !important;
-                }
-                .loading-circle {
-                    position: absolute;
-                    display:flex;
-                    align-items: center;
-                    justify-content: center;
-                    width: 50px;
-                    height: 50px;
-                    border-radius: 50%;
-                    border: 3px solid #ccc;
-                    border-top-color: #333;
-                    animation: spin 1s infinite linear;
-                }
-        
-                @keyframes spin {
-                    0% {
-                        transform: rotate(0deg);
-                    }
-                    100% {
-                        transform: rotate(360deg);
-                    }
+                    height: calc(100% - 50px);
                 }
             }
         }
diff --git a/src/client/views/nodes/DiagramBox.tsx b/src/client/views/nodes/DiagramBox.tsx
index 220c43ead..08c889158 100644
--- a/src/client/views/nodes/DiagramBox.tsx
+++ b/src/client/views/nodes/DiagramBox.tsx
@@ -39,9 +39,11 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     @observable menuState = menuState.justCreated;
     @observable renderDiv: React.ReactNode;
     @observable inputValue = '';
+    @observable createInputValue = '';
     @observable loading = false;
     @observable errorMessage = '';
     @observable mermaidCode = '';
+    @observable isExampleMenuOpen = false;
 
     @action handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
         this.inputValue = e.target.value;
@@ -115,7 +117,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             const { svg, bindFunctions } = await this.mermaidDiagram(str);
             return { svg, bindFunctions };
         } catch (error) {
-            console.error('Error rendering mermaid diagram:', error);
+            // console.error('Error rendering mermaid diagram:', error);
             return { svg: '', bindFunctions: undefined };
         }
     };
@@ -127,6 +129,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             const dashDiv = document.getElementById('dashDiv' + this.Document.title);
             if (dashDiv) {
                 dashDiv.innerHTML = svg;
+                // this.changeHeightWidth(svg);
                 if (bindFunctions) {
                     bindFunctions(dashDiv);
                 }
@@ -135,6 +138,20 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             console.error('Error rendering Mermaid:', error);
         }
     }
+    changeHeightWidth(svgString: string) {
+        const pattern = /width="([\d.]+)"\s*height="([\d.]+)"/;
+
+        const match = svgString.match(pattern);
+
+        if (match) {
+            const width = parseFloat(match[1]);
+            const height = parseFloat(match[2]);
+            console.log(width);
+            console.log(height);
+            this.Document.width = width;
+            this.Document.height = height;
+        }
+    }
     @action handleRenderClick = () => {
         this.mermaidCode = '';
         if (this.inputValue) {
@@ -143,13 +160,17 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     };
     @action async generateMermaidCode() {
         console.log('Generating Mermaid Code');
+        const dashDiv = document.getElementById('dashDiv' + this.Document.title);
+        if (dashDiv) {
+            dashDiv.innerHTML = '';
+        }
         this.loading = true;
         let prompt = '';
         prompt = 'Write this in mermaid code and only give me the mermaid code: ' + this.inputValue;
         console.log('there is no text save');
         // }
         const res = await gptAPICall(prompt, GPTCallType.MERMAID);
-        this.loading = false;
+        this.loading = true;
         if (res === 'Error connecting with API.') {
             // If GPT call failed
             console.error('GPT call failed');
@@ -167,7 +188,6 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         }
         this.renderMermaidAsync.call(this, this.removeWords(this.mermaidCode));
         this.Document.gptMermaidCode = this.removeWords(this.mermaidCode);
-        this.loading = false;
     }
     isValidCode = (html: string) => true;
     removeWords(inputStrIn: string) {
@@ -225,9 +245,9 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                                     console.log(linkedDocs.length);
                                     if (linkedDocs.length !== 0) {
                                         const linkedText = (linkedDocs[0].text as RichTextField).Text;
-                                        mermaidCode += Math.abs(rectangle.x) + this.getTextInBox(rectangle, textArray) + '-->|' + linkedText + '|' + Math.abs(rectangle2.x) + this.getTextInBox(rectangle2, textArray) + ';';
+                                        mermaidCode += Math.abs(rectangle.x) + this.getTextInBox(rectangle, textArray) + '---|' + linkedText + '|' + Math.abs(rectangle2.x) + this.getTextInBox(rectangle2, textArray) + ';';
                                     } else {
-                                        mermaidCode += Math.abs(rectangle.x) + this.getTextInBox(rectangle, textArray) + '-->' + Math.abs(rectangle2.x) + this.getTextInBox(rectangle2, textArray) + ';';
+                                        mermaidCode += Math.abs(rectangle.x) + this.getTextInBox(rectangle, textArray) + '---' + Math.abs(rectangle2.x) + this.getTextInBox(rectangle2, textArray) + ';';
                                     }
                                 }
                             }
@@ -336,13 +356,21 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                             Generate
                         </button>
                     </div>
-                    <div id={'dashDiv' + this.Document.title} className="diagramBox" />
+                    {this.mermaidCode ? (
+                        <div id={'dashDiv' + this.Document.title} className="diagramBox" />
+                    ) : (
+                        <div>{this.loading ? <div className="loading-circle" /> : <div>{this.errorMessage ? this.errorMessage : 'Insert prompt to generate diagram'}</div>}</div>
+                    )}
                 </div>
             </div>
         );
     }
 
     renderMermaidCode(): React.ReactNode {
+        let title = 'asd';
+        if (typeof this.Document.title === 'string') {
+            title = this.removeWhitespace(this.Document.title);
+        }
         return (
             <div ref={this._dragRef} className="DiagramBox-wrapper">
                 <div className="content">
@@ -350,18 +378,130 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                         <button className="backButton" type="button" onClick={this.optionButton}>
                             Back
                         </button>
-                        <textarea placeholder="Enter Mermaid Code" onChange={this.handleInputChangeEditor} onInput={e => this.autoResize(e.target as HTMLTextAreaElement)} />
+                        <textarea value={this.createInputValue} className={'textarea' + title} placeholder="Enter Mermaid Code" onChange={this.handleInputChangeEditor} onInput={e => this.autoResize(e.target as HTMLTextAreaElement)} />
+                        <button className="exampleButton" type="button" onClick={this.exampleButton}>
+                            Examples
+                        </button>
                     </div>
+                    {this.isExampleMenuOpen && (
+                        <div className="exampleButtonContainer">
+                            <button type="button" onClick={this.flowButton}>
+                                Flow
+                            </button>
+                            <button type="button" onClick={this.pieButton}>
+                                Pie
+                            </button>
+                            <button type="button" onClick={this.timelineButton}>
+                                Timeline
+                            </button>
+                            <button type="button" onClick={this.classButton}>
+                                Class
+                            </button>
+                            <button type="button" onClick={this.mindmapButton}>
+                                Mindmap
+                            </button>
+                        </div>
+                    )}
                     <div id={'dashDiv' + this.Document.title} className="diagramBox" />
                 </div>
             </div>
         );
     }
+    exampleButton = () => {
+        if (this.isExampleMenuOpen) {
+            this.isExampleMenuOpen = false;
+        } else {
+            this.isExampleMenuOpen = true;
+        }
+    };
+    removeWhitespace(str: string): string {
+        return str.replace(/\s+/g, '');
+    }
+    flowButton = () => {
+        this.createInputValue = `flowchart TD
+        A[Christmas] -->|Get money| B(Go shopping)
+        B --> C{Let me think}
+        C -->|One| D[Laptop]
+        C -->|Two| E[iPhone]
+        C -->|Three| F[fa:fa-car Car]`;
+        this.changeSizeManually(115);
+    };
+    pieButton = () => {
+        this.createInputValue = `pie title Pets adopted by volunteers
+        "Dogs" : 386
+        "Cats" : 85
+        "Rats" : 15`;
+        this.changeSizeManually(78);
+    };
+    timelineButton = () => {
+        this.createInputValue = `gantt
+        title A Gantt Diagram
+        dateFormat  YYYY-MM-DD
+        section Section
+        A task           :a1, 2014-01-01, 30d
+        Another task     :after a1  , 20d
+        section Another
+        Task in sec      :2014-01-12  , 12d
+        another task      : 24d`;
+    };
+    classButton = () => {
+        this.createInputValue = `classDiagram
+        Animal <|-- Duck
+        Animal <|-- Fish
+        Animal <|-- Zebra
+        Animal : +int age
+        Animal : +String gender
+        Animal: +isMammal()
+        Animal: +mate()
+        class Duck{
+            +String beakColor
+            +swim()
+            +quack()
+        }
+        class Fish{
+            -int sizeInFeet
+            -canEat()
+        }
+        class Zebra{
+            +bool is_wild
+            +run()
+        }`;
+    };
+    mindmapButton = () => {
+        this.createInputValue = `mindmap
+        root((mindmap))
+            Origins
+            Long history
+            ::icon(fa fa-book)
+            Popularisation
+                British popular psychology author Tony Buzan
+            Research
+            On effectivness<br/>and features
+            On Automatic creation
+                Uses
+                    Creative techniques
+                    Strategic planning
+                    Argument mapping
+            Tools
+            Pen and paper
+            Mermaid`;
+    };
     handleInputChangeEditor = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
         if (typeof e.target.value === 'string') {
+            this.createInputValue = e.target.value;
             this.renderMermaidAsync(e.target.value);
+            this.autoResize(e.target);
+            console.log('hellsad');
         }
     };
+    changeSizeManually(size: number) {
+        if (typeof this.Document.title === 'string') {
+            const textarea = document.querySelector<HTMLTextAreaElement>('textarea.textarea' + this.removeWhitespace(this.Document.title));
+            if (textarea) {
+                textarea.style.height = size + 'px';
+            }
+        }
+    }
     timeline = `gantt
     title College Timeline
     dateFormat  YYYY-MM-DD
-- 
cgit v1.2.3-70-g09d2


From 53465ea035635f4fff53b7f481e0116b139b1e10 Mon Sep 17 00:00:00 2001
From: Zachary Zhang <zacharyzhang7@gmail.com>
Date: Thu, 13 Jun 2024 14:25:53 -0400
Subject: add LR vs TD graph detector

---
 src/client/views/nodes/DiagramBox.scss | 91 ++++++++++++++++++++++++++++++++++
 src/client/views/nodes/DiagramBox.tsx  | 63 +++++++++++++----------
 2 files changed, 128 insertions(+), 26 deletions(-)

(limited to 'src/client/views/nodes/DiagramBox.tsx')

diff --git a/src/client/views/nodes/DiagramBox.scss b/src/client/views/nodes/DiagramBox.scss
index 5b12c6f89..d73dd2a97 100644
--- a/src/client/views/nodes/DiagramBox.scss
+++ b/src/client/views/nodes/DiagramBox.scss
@@ -35,6 +35,97 @@
         flex-direction: column;
         align-items: center;
         justify-content: center;
+        .contentCode{
+            overflow: hidden;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            flex-direction:row;
+            padding:10px;
+            width:100%;
+            height:100%;
+            .topbar{
+                .backButtonDrawing{
+                    padding: 5px 10px;
+                    height:23px;
+                    border-radius: 10px;
+                    text-align: center;
+                    padding:0;
+                    width:50px;
+                    font-size:10px;
+                    position:absolute;
+                    top:10px;
+                    left:10px;
+                }
+                p{
+                    margin-left:60px
+                }
+            }
+            .search-bar {
+                overflow:hidden;
+                position:absolute;
+                top:0;
+                .backButton{
+                    text-align: center;
+                    padding:0;
+                    width:50px;
+                    font-size:10px;
+
+                }
+                .exampleButton{
+                    width:100px;
+                    height:30px;
+                }
+                display: flex;
+                flex-wrap: wrap;
+                justify-content: space-between;
+                align-items: center;
+                width: 100%;
+                button {
+                    padding: 5px 10px;
+                    width:80px;
+                    height:23px;
+                    border-radius: 3px;
+                }
+            }
+            .exampleButtonContainer{
+                display:flex;
+                flex-direction: column;
+                position: absolute;
+                top:37px;
+                right:30px;
+                width:50px;
+                z-index: 200;
+                button{
+                    width:70px;
+                    margin:2px;
+                    padding:0px;
+                    height:15px;
+                    border-radius: 3px;
+                }
+            }
+            textarea {
+                position:relative;
+                width:40%;
+                height: 100%;
+                height: calc(100% - 25px);
+                top:15px;
+                resize:none;
+                overflow: hidden;
+            }
+            .diagramBox{
+                flex: 1;
+                display: flex;
+                justify-content: center;
+                align-items: center;
+                svg{
+                    position: relative;
+                    top:25;
+                    max-width: none !important;
+                    height: calc(100% - 50px);
+                }
+            }
+        }
         .content {
             overflow: hidden;
             display: flex;
diff --git a/src/client/views/nodes/DiagramBox.tsx b/src/client/views/nodes/DiagramBox.tsx
index 08c889158..068c92e6b 100644
--- a/src/client/views/nodes/DiagramBox.tsx
+++ b/src/client/views/nodes/DiagramBox.tsx
@@ -203,6 +203,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             const rectangleArray = docArray.filter(doc => doc.title === 'rectangle' || doc.title === 'circle');
             const lineArray = docArray.filter(doc => doc.title === 'line' || doc.title === 'stroke');
             const textArray = docArray.filter(doc => doc.type === 'rich text');
+            this.isLeftRightDiagram(docArray);
             const timeoutPromise = () =>
                 new Promise(resolve => {
                     setTimeout(resolve, 0);
@@ -212,7 +213,11 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             console.log(inkStrokeArray.length);
             console.log(lineArray.length);
             if (inkStrokeArray[0] && inkStrokeArray.length === lineArray.length) {
-                mermaidCode = 'graph TD;';
+                if (this.isLeftRightDiagram(docArray)) {
+                    mermaidCode = 'graph LR;';
+                } else {
+                    mermaidCode = 'graph TD;';
+                }
                 const inkingStrokeArray = inkStrokeArray.map(stroke => stroke?.ComponentView);
                 for (let i = 0; i < rectangleArray.length; i++) {
                     const rectangle = rectangleArray[i];
@@ -263,6 +268,29 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             }
         }
     }
+    isLeftRightDiagram = (docArray: Doc[]) => {
+        const filteredDocs = docArray.filter(doc => doc.title === 'rectangle' || doc.title === 'circle');
+        const xDoc = filteredDocs.map(doc => doc.x) as number[];
+        const minX = Math.min(...xDoc);
+        const xWidthDoc = filteredDocs.map(doc => {
+            if (typeof doc.x === 'number' && typeof doc.width === 'number') {
+                return doc.x + doc.width;
+            }
+        }) as number[];
+        const maxX = Math.max(...xWidthDoc);
+        const yDoc = filteredDocs.map(doc => doc.y) as number[];
+        const minY = Math.min(...yDoc);
+        const yHeightDoc = filteredDocs.map(doc => {
+            if (typeof doc.x === 'number' && typeof doc.width === 'number') {
+                return doc.x + doc.width;
+            }
+        }) as number[];
+        const maxY = Math.max(...yHeightDoc);
+        if (maxX - minX > maxY - minY) {
+            return true;
+        }
+        return false;
+    };
     testInkingStroke = () => {
         if (this.Document.data instanceof List) {
             const docArray: Doc[] = DocListCast(this.Document.data);
@@ -295,10 +323,6 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         }
         return false;
     };
-    autoResize(element: HTMLTextAreaElement): void {
-        element.style.height = '5px';
-        element.style.height = element.scrollHeight + 'px';
-    }
     drawingButton = () => {
         this.Document.menuState = 'drawing';
     };
@@ -351,7 +375,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                         <button className="backButton" type="button" onClick={this.optionButton}>
                             Back
                         </button>
-                        <textarea value={this.inputValue} placeholder="Enter GPT prompt" onChange={this.handleInputChange} onInput={e => this.autoResize(e.target as HTMLTextAreaElement)} />
+                        <textarea value={this.inputValue} placeholder="Enter GPT prompt" onChange={this.handleInputChange} />
                         <button className="generateButton" type="button" onClick={this.handleRenderClick}>
                             Generate
                         </button>
@@ -367,18 +391,13 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     }
 
     renderMermaidCode(): React.ReactNode {
-        let title = 'asd';
-        if (typeof this.Document.title === 'string') {
-            title = this.removeWhitespace(this.Document.title);
-        }
         return (
             <div ref={this._dragRef} className="DiagramBox-wrapper">
-                <div className="content">
+                <div className="contentCode">
                     <div className="search-bar">
                         <button className="backButton" type="button" onClick={this.optionButton}>
                             Back
                         </button>
-                        <textarea value={this.createInputValue} className={'textarea' + title} placeholder="Enter Mermaid Code" onChange={this.handleInputChangeEditor} onInput={e => this.autoResize(e.target as HTMLTextAreaElement)} />
                         <button className="exampleButton" type="button" onClick={this.exampleButton}>
                             Examples
                         </button>
@@ -402,6 +421,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                             </button>
                         </div>
                     )}
+                    <textarea value={this.createInputValue} placeholder="Enter Mermaid Code" onChange={this.handleInputChangeEditor} />
                     <div id={'dashDiv' + this.Document.title} className="diagramBox" />
                 </div>
             </div>
@@ -414,9 +434,6 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             this.isExampleMenuOpen = true;
         }
     };
-    removeWhitespace(str: string): string {
-        return str.replace(/\s+/g, '');
-    }
     flowButton = () => {
         this.createInputValue = `flowchart TD
         A[Christmas] -->|Get money| B(Go shopping)
@@ -424,14 +441,14 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         C -->|One| D[Laptop]
         C -->|Two| E[iPhone]
         C -->|Three| F[fa:fa-car Car]`;
-        this.changeSizeManually(115);
+        this.renderMermaidAsync(this.createInputValue);
     };
     pieButton = () => {
         this.createInputValue = `pie title Pets adopted by volunteers
         "Dogs" : 386
         "Cats" : 85
         "Rats" : 15`;
-        this.changeSizeManually(78);
+        this.renderMermaidAsync(this.createInputValue);
     };
     timelineButton = () => {
         this.createInputValue = `gantt
@@ -443,6 +460,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         section Another
         Task in sec      :2014-01-12  , 12d
         another task      : 24d`;
+        this.renderMermaidAsync(this.createInputValue);
     };
     classButton = () => {
         this.createInputValue = `classDiagram
@@ -466,6 +484,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             +bool is_wild
             +run()
         }`;
+        this.renderMermaidAsync(this.createInputValue);
     };
     mindmapButton = () => {
         this.createInputValue = `mindmap
@@ -485,23 +504,15 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             Tools
             Pen and paper
             Mermaid`;
+        this.renderMermaidAsync(this.createInputValue);
     };
     handleInputChangeEditor = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
         if (typeof e.target.value === 'string') {
             this.createInputValue = e.target.value;
             this.renderMermaidAsync(e.target.value);
-            this.autoResize(e.target);
             console.log('hellsad');
         }
     };
-    changeSizeManually(size: number) {
-        if (typeof this.Document.title === 'string') {
-            const textarea = document.querySelector<HTMLTextAreaElement>('textarea.textarea' + this.removeWhitespace(this.Document.title));
-            if (textarea) {
-                textarea.style.height = size + 'px';
-            }
-        }
-    }
     timeline = `gantt
     title College Timeline
     dateFormat  YYYY-MM-DD
-- 
cgit v1.2.3-70-g09d2


From 6d8249f4f54a00bcbef740a3cd2114a6ddd77c55 Mon Sep 17 00:00:00 2001
From: Zachary Zhang <zacharyzhang7@gmail.com>
Date: Tue, 18 Jun 2024 14:33:39 -0400
Subject: ink stuff

---
 src/client/views/nodes/DiagramBox.tsx | 224 +++++++++++++++++++++++-----------
 1 file changed, 155 insertions(+), 69 deletions(-)

(limited to 'src/client/views/nodes/DiagramBox.tsx')

diff --git a/src/client/views/nodes/DiagramBox.tsx b/src/client/views/nodes/DiagramBox.tsx
index 068c92e6b..15e569949 100644
--- a/src/client/views/nodes/DiagramBox.tsx
+++ b/src/client/views/nodes/DiagramBox.tsx
@@ -1,3 +1,4 @@
+/* eslint-disable prettier/prettier */
 /* eslint-disable jsx-a11y/control-has-associated-label */
 import mermaid from 'mermaid';
 import { action, makeObservable, observable, reaction } from 'mobx';
@@ -6,16 +7,18 @@ import * as React from 'react';
 import { Doc, DocListCast } from '../../../fields/Doc';
 import { List } from '../../../fields/List';
 import { RichTextField } from '../../../fields/RichTextField';
-import { DocCast } from '../../../fields/Types';
+import { DocCast,BoolCast } from '../../../fields/Types';
 import { GPTCallType, gptAPICall } from '../../apis/gpt/GPT';
 import { DocumentType } from '../../documents/DocumentTypes';
 import { Docs } from '../../documents/Documents';
 import { DocumentManager } from '../../util/DocumentManager';
 import { LinkManager } from '../../util/LinkManager';
 import { ViewBoxAnnotatableComponent } from '../DocComponent';
-import { InkingStroke } from '../InkingStroke';
+import { InkingStroke} from '../InkingStroke';
 import './DiagramBox.scss';
 import { FieldView, FieldViewProps } from './FieldView';
+import { PointData } from '../../../pen-gestures/GestureTypes';
+import { InkField } from '../../../fields/InkField';
 
 enum menuState {
     option,
@@ -67,22 +70,22 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         if (typeof this.Document.drawingMermaidCode === 'string' && this.Document.menuState === 'drawing') {
             this.renderMermaidAsync(this.Document.drawingMermaidCode);
         }
-        console.log(this.Document.title);
-        // this.renderMermaidAsync(this.timeline);
+        this.renderMermaidAsync(this.timeline);
         // this is so that ever time a new doc, text node or ink node, is created, this.createMermaidCode will run which will create a save
-        reaction(
-            () => DocListCast(this.Document.data),
-            () => this.convertDrawingToMermaidCode(),
-            { fireImmediately: true }
-        );
-        reaction(
-            () =>
-                DocListCast(this.Document.data)
-                    .filter(doc => doc.type === 'rich text')
-                    .map(doc => (doc.text as RichTextField).Text),
-            () => this.convertDrawingToMermaidCode(),
-            { fireImmediately: true }
-        );
+        // reaction(
+        //     () => DocListCast(this.Document.data),
+        //     () => this.lockInkStroke(),
+        //     { fireImmediately: true }
+        // );
+        // reaction(
+        //     () =>
+        //         DocListCast(this.Document.data)
+        //             .filter(doc => doc.type === 'rich text')
+        //             .map(doc => (doc.text as RichTextField).Text),
+        //     () => this.convertDrawingToMermaidCode(),
+        //     { fireImmediately: true }
+        // );
+        this.lockInkStroke();
     }
     componentDidUpdate = () => {
         if (typeof this.Document.drawingMermaidCode === 'string' && this.Document.menuState === 'drawing') {
@@ -109,7 +112,6 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             default:
                 this.menuState = menuState.option;
                 this.renderDiv = this.renderOption();
-                console.log(this.renderDiv);
         }
     }
     renderMermaid = async (str: string) => {
@@ -177,19 +179,13 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             this.errorMessage = 'GPT call failed; please try again.';
         } else if (res !== null) {
             // If GPT call succeeded, set htmlCode;;; TODO: check if valid html
-            if (this.isValidCode(res)) {
-                this.mermaidCode = res;
-                console.log('GPT call succeeded:' + res);
-                this.errorMessage = '';
-            } else {
-                console.error('GPT call succeeded but invalid html; please try again.');
-                this.errorMessage = 'GPT call succeeded but invalid html; please try again.';
-            }
+            this.mermaidCode = res;
+            console.log('GPT call succeeded:' + res);
+            this.errorMessage = '';
         }
         this.renderMermaidAsync.call(this, this.removeWords(this.mermaidCode));
         this.Document.gptMermaidCode = this.removeWords(this.mermaidCode);
     }
-    isValidCode = (html: string) => true;
     removeWords(inputStrIn: string) {
         const inputStr = inputStrIn.replace('```mermaid', '');
         return inputStr.replace('```', '');
@@ -203,21 +199,18 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             const rectangleArray = docArray.filter(doc => doc.title === 'rectangle' || doc.title === 'circle');
             const lineArray = docArray.filter(doc => doc.title === 'line' || doc.title === 'stroke');
             const textArray = docArray.filter(doc => doc.type === 'rich text');
-            this.isLeftRightDiagram(docArray);
             const timeoutPromise = () =>
                 new Promise(resolve => {
                     setTimeout(resolve, 0);
                 });
             await timeoutPromise();
             const inkStrokeArray = lineArray.map(doc => DocumentManager.Instance.getDocumentView(doc, this.DocumentView?.())).filter(inkView => inkView?.ComponentView instanceof InkingStroke);
-            console.log(inkStrokeArray.length);
-            console.log(lineArray.length);
             if (inkStrokeArray[0] && inkStrokeArray.length === lineArray.length) {
-                if (this.isLeftRightDiagram(docArray)) {
-                    mermaidCode = 'graph LR;';
-                } else {
-                    mermaidCode = 'graph TD;';
-                }
+                // if (this.isLeftRightDiagram(docArray)) {
+                //     mermaidCode = 'graph LR;';
+                // } else {
+                //     mermaidCode = 'graph TD;';
+                // }
                 const inkingStrokeArray = inkStrokeArray.map(stroke => stroke?.ComponentView);
                 for (let i = 0; i < rectangleArray.length; i++) {
                     const rectangle = rectangleArray[i];
@@ -232,8 +225,6 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                             ?.inkScaledData()
                             .inkData.map(coord => coord.Y)
                             .map(doc => doc * inkScaleY);
-                        console.log(inkingStrokeArray.length);
-                        console.log(lineArray.length);
                         // need to minX and minY to since the inkStroke.x and.y is not relative to the doc. so I have to do some calcluations
                         const minX: number = Math.min(...inkStrokeXArray);
                         const minY: number = Math.min(...inkStrokeYArray);
@@ -247,7 +238,6 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                                 if (this.isPointInBox(rectangle2, [endX, endY]) && typeof rectangle.x === 'number' && typeof rectangle2.x === 'number') {
                                     diagramExists = true;
                                     const linkedDocs: Doc[] = LinkManager.Instance.getAllRelatedLinks(lineArray[j]).map(d => DocCast(LinkManager.getOppositeAnchor(d, lineArray[j])));
-                                    console.log(linkedDocs.length);
                                     if (linkedDocs.length !== 0) {
                                         const linkedText = (linkedDocs[0].text as RichTextField).Text;
                                         mermaidCode += Math.abs(rectangle.x) + this.getTextInBox(rectangle, textArray) + '---|' + linkedText + '|' + Math.abs(rectangle2.x) + this.getTextInBox(rectangle2, textArray) + ';';
@@ -268,39 +258,137 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             }
         }
     }
-    isLeftRightDiagram = (docArray: Doc[]) => {
-        const filteredDocs = docArray.filter(doc => doc.title === 'rectangle' || doc.title === 'circle');
-        const xDoc = filteredDocs.map(doc => doc.x) as number[];
-        const minX = Math.min(...xDoc);
-        const xWidthDoc = filteredDocs.map(doc => {
-            if (typeof doc.x === 'number' && typeof doc.width === 'number') {
-                return doc.x + doc.width;
-            }
-        }) as number[];
-        const maxX = Math.max(...xWidthDoc);
-        const yDoc = filteredDocs.map(doc => doc.y) as number[];
-        const minY = Math.min(...yDoc);
-        const yHeightDoc = filteredDocs.map(doc => {
-            if (typeof doc.x === 'number' && typeof doc.width === 'number') {
-                return doc.x + doc.width;
-            }
-        }) as number[];
-        const maxY = Math.max(...yHeightDoc);
-        if (maxX - minX > maxY - minY) {
-            return true;
-        }
-        return false;
-    };
-    testInkingStroke = () => {
+    async lockInkStroke() {
         if (this.Document.data instanceof List) {
             const docArray: Doc[] = DocListCast(this.Document.data);
+            const rectangleArray = docArray.filter(doc => doc.title === 'rectangle' || doc.title === 'circle');
+            if(rectangleArray[0]){
+                console.log(rectangleArray[0].x)
+            }
             const lineArray = docArray.filter(doc => doc.title === 'line' || doc.title === 'stroke');
-            setTimeout(() => {
-                const inkStrokeArray = lineArray.map(doc => DocumentManager.Instance.getDocumentView(doc, this.DocumentView?.())).filter(inkView => inkView?.ComponentView instanceof InkingStroke);
-                console.log(inkStrokeArray);
-            });
+            const timeoutPromise = () =>
+                new Promise(resolve => {
+                    setTimeout(resolve, 0);
+                });
+            await timeoutPromise();
+            const inkStrokeArray = lineArray.map(doc => DocumentManager.Instance.getDocumentView(doc, this.DocumentView?.())).filter(inkView => inkView?.ComponentView instanceof InkingStroke);
+            const inkingStrokeArray = inkStrokeArray.map(stroke => stroke?.ComponentView);
+            for (let j = 0; j < lineArray.length; j++) {
+                const inkScaleX = (inkingStrokeArray[j] as InkingStroke)?.inkScaledData().inkScaleX;
+                const inkScaleY = (inkingStrokeArray[j] as InkingStroke)?.inkScaledData().inkScaleY;
+                const inkStrokeXArray = (inkingStrokeArray[j] as InkingStroke)
+                    ?.inkScaledData()
+                    .inkData.map(coord => coord.X)
+                    .map(doc => doc * inkScaleX);
+                const inkStrokeYArray = (inkingStrokeArray[j] as InkingStroke)
+                    ?.inkScaledData()
+                    .inkData.map(coord => coord.Y)
+                    .map(doc => doc * inkScaleY);
+                // need to minX and minY to since the inkStroke.x and.y is not relative to the doc. so I have to do some calcluations
+                const minX: number = Math.min(...inkStrokeXArray);
+                const minY: number = Math.min(...inkStrokeYArray);
+                const startX = inkStrokeXArray[0] - minX + (lineArray[j]?.x as number);
+                const startY = inkStrokeYArray[0] - minY + (lineArray[j]?.y as number);
+                const endX = inkStrokeXArray[inkStrokeXArray.length - 1] - minX + (lineArray[j].x as number);
+                const endY = inkStrokeYArray[inkStrokeYArray.length - 1] - minY + (lineArray[j].y as number);
+                let closestStartRect:Doc=lineArray[0];
+                let closestStartDistance=9999999;
+                let closestEndRect:Doc=lineArray[0];
+                let closestEndDistance=9999999;
+                rectangleArray.forEach(rectangle => {
+                    const midPoint=this.getMidPoint(rectangle)
+                    if(this.euclideanDistance(midPoint.X,midPoint.Y,startX,startY)<closestStartDistance&&this.euclideanDistance(midPoint.X,midPoint.Y,endX,endY)<closestEndDistance){
+                        if(this.euclideanDistance(midPoint.X,midPoint.Y,startX,startY)<this.euclideanDistance(midPoint.X,midPoint.Y,endX,endY)){
+                            closestStartDistance=this.euclideanDistance(midPoint.X,midPoint.Y,startX,startY);
+                            closestStartRect=rectangle
+                        }
+                        else{
+                            closestEndDistance=this.euclideanDistance(midPoint.X,midPoint.Y,startX,startY);
+                            closestEndRect=rectangle
+                        }
+                    }
+                    else if(this.euclideanDistance(midPoint.X,midPoint.Y,startX,startY)<closestStartDistance){
+                        closestStartDistance=this.euclideanDistance(midPoint.X,midPoint.Y,startX,startY);
+                        closestStartRect=rectangle
+                    }
+                    else if(this.euclideanDistance(midPoint.X,midPoint.Y,endX,endY)<closestEndDistance){
+                        closestEndDistance=this.euclideanDistance(midPoint.X,midPoint.Y,startX,startY);
+                        closestEndRect=rectangle
+                    }
+                    
+                });
+                const inkToDelete:Doc=lineArray[j];
+                if(typeof closestStartRect.x==='number'&&typeof closestStartRect.y==='number'&&typeof closestEndRect.x==='number'&&typeof closestEndRect.y==='number'&&typeof closestStartRect.width==='number'&&typeof closestStartRect.height==='number'){
+                    const points: PointData[] = [
+                        { X: closestStartRect.x, Y: closestStartRect.y },
+                        { X: closestStartRect.x, Y: closestStartRect.y },
+                        { X: closestEndRect.x, Y: closestEndRect.y },
+                        { X: closestEndRect.x, Y: closestEndRect.y }
+                    ];
+                    const newInkDoc:Doc=Docs.Create.InkDocument(
+                        points,
+                        { title: 'stroke',
+                        x: closestStartRect.x+closestStartRect.width/2,
+                        y: closestStartRect.y+closestStartRect.height/2,
+                        _width: closestStartRect.width,
+                        _height: closestStartRect.height,
+                        stroke_showLabel: BoolCast(Doc.UserDoc().activeInkHideTextLabels)}, // prettier-ignore
+                        1)
+                    
+                    DocumentManager.Instance.AddViewRenderedCb(this.Document, (docViewForYourCollection) => {
+                        if (docViewForYourCollection && docViewForYourCollection.ComponentView) {
+                            if (docViewForYourCollection.ComponentView.addDocument&&docViewForYourCollection.ComponentView.removeDocument) {
+                                if(!inkToDelete.transformed){
+                                    docViewForYourCollection.ComponentView?.removeDocument(inkToDelete)
+                                    docViewForYourCollection.ComponentView?.addDocument(newInkDoc);
+                                    newInkDoc.transformed=true;
+    
+                                }
+                                const bruh2= DocListCast(this.Document.data).filter(doc => doc.title === 'line' || doc.title === 'stroke').map(doc => DocumentManager.Instance.getDocumentView(doc, this.DocumentView?.())).filter(inkView => inkView?.ComponentView instanceof InkingStroke).map(stroke => stroke?.ComponentView);
+                                console.log(bruh2)
+                                console.log((bruh2[0] as InkingStroke)?.inkScaledData())
+                            }
+                        }
+                    });    
+                }           
+            }
         }
-    };
+    }
+    getMidPoint(rectangle:Doc){
+        let midPoint={X:0,Y:0}
+        if(typeof rectangle.x ==='number' && typeof rectangle.width==='number'&&typeof rectangle.y ==='number' && typeof rectangle.height==='number'){
+            midPoint={X:rectangle.x+rectangle.width/2,Y:rectangle.y+rectangle.height/2};
+        }
+        return midPoint
+    }
+    euclideanDistance(x1: number, y1: number, x2: number, y2: number): number {
+        const deltaX = x2 - x1;
+        const deltaY = y2 - y1;
+        return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
+    }
+    // isLeftRightDiagram = (docArray: Doc[]) => {
+    //     const filteredDocs = docArray.filter(doc => doc.title === 'rectangle' || doc.title === 'circle');
+    //     const xDoc = filteredDocs.map(doc => doc.x) as number[];
+    //     const minX = Math.min(...xDoc);
+    //     const xWidthDoc = filteredDocs.map(doc => {
+    //         if (typeof doc.x === 'number' && typeof doc.width === 'number') {
+    //             return doc.x + doc.width;
+    //         }
+    //     }) as number[];
+    //     const maxX = Math.max(...xWidthDoc);
+    //     const yDoc = filteredDocs.map(doc => doc.y) as number[];
+    //     const minY = Math.min(...yDoc);
+    //     const yHeightDoc = filteredDocs.map(doc => {
+    //         if (typeof doc.x === 'number' && typeof doc.width === 'number') {
+    //             return doc.x + doc.width;
+    //         }
+    //     }) as number[];
+    //     const maxY = Math.max(...yHeightDoc);
+    //     if (maxX - minX > maxY - minY) {
+    //         return true;
+    //     }
+    //     return false;
+    // };
     getTextInBox = (box: Doc, richTextArray: Doc[]): string => {
         for (let i = 0; i < richTextArray.length; i++) {
             const textDoc = richTextArray[i];
@@ -351,7 +439,6 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         );
     }
     renderDrawing(): React.ReactNode {
-        console.log(this.Document.mermaidCode);
         return (
             <div ref={this._dragRef} className="DiagramBox-wrapper">
                 <div className="content">
@@ -510,7 +597,6 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         if (typeof e.target.value === 'string') {
             this.createInputValue = e.target.value;
             this.renderMermaidAsync(e.target.value);
-            console.log('hellsad');
         }
     };
     timeline = `gantt
-- 
cgit v1.2.3-70-g09d2


From ebb77ad1c5d7a6edb83668bed3688799bd2fc4fe Mon Sep 17 00:00:00 2001
From: Zachary Zhang <zacharyzhang7@gmail.com>
Date: Tue, 18 Jun 2024 14:53:35 -0400
Subject: working line lock

---
 src/client/views/nodes/DiagramBox.tsx | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

(limited to 'src/client/views/nodes/DiagramBox.tsx')

diff --git a/src/client/views/nodes/DiagramBox.tsx b/src/client/views/nodes/DiagramBox.tsx
index 15e569949..fcf6e580b 100644
--- a/src/client/views/nodes/DiagramBox.tsx
+++ b/src/client/views/nodes/DiagramBox.tsx
@@ -318,20 +318,34 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                     
                 });
                 const inkToDelete:Doc=lineArray[j];
-                if(typeof closestStartRect.x==='number'&&typeof closestStartRect.y==='number'&&typeof closestEndRect.x==='number'&&typeof closestEndRect.y==='number'&&typeof closestStartRect.width==='number'&&typeof closestStartRect.height==='number'){
+                if(typeof closestStartRect.x==='number'&&typeof closestStartRect.y==='number'&&typeof closestEndRect.x==='number'&&typeof closestEndRect.y==='number'&&typeof closestStartRect.width==='number'&&typeof closestStartRect.height==='number'&&typeof closestEndRect.height==='number'&&typeof closestEndRect.width==='number'){
                     const points: PointData[] = [
                         { X: closestStartRect.x, Y: closestStartRect.y },
                         { X: closestStartRect.x, Y: closestStartRect.y },
                         { X: closestEndRect.x, Y: closestEndRect.y },
                         { X: closestEndRect.x, Y: closestEndRect.y }
                     ];
+                    let inkX=0;
+                    let inkY=0;
+                    if(this.getMidPoint(closestEndRect).X<this.getMidPoint(closestStartRect).X){
+                        inkX=this.getMidPoint(closestEndRect).X
+                    }
+                    else{
+                        inkX=this.getMidPoint(closestStartRect).X
+                    }
+                    if(this.getMidPoint(closestEndRect).Y<this.getMidPoint(closestStartRect).Y){
+                        inkY=this.getMidPoint(closestEndRect).Y
+                    }
+                    else{
+                        inkY=this.getMidPoint(closestStartRect).Y
+                    }
                     const newInkDoc:Doc=Docs.Create.InkDocument(
                         points,
                         { title: 'stroke',
-                        x: closestStartRect.x+closestStartRect.width/2,
-                        y: closestStartRect.y+closestStartRect.height/2,
-                        _width: closestStartRect.width,
-                        _height: closestStartRect.height,
+                        x: inkX,
+                        y: inkY,
+                        _width: Math.abs(closestEndRect.x+closestEndRect.width/2-closestStartRect.x-closestStartRect.width/2),
+                        _height: Math.abs(closestEndRect.y+closestEndRect.height/2-closestStartRect.y-closestStartRect.height/2),
                         stroke_showLabel: BoolCast(Doc.UserDoc().activeInkHideTextLabels)}, // prettier-ignore
                         1)
                     
@@ -341,7 +355,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                                 if(!inkToDelete.transformed){
                                     docViewForYourCollection.ComponentView?.removeDocument(inkToDelete)
                                     docViewForYourCollection.ComponentView?.addDocument(newInkDoc);
-                                    newInkDoc.transformed=true;
+                                    newInkDoc.transformed=false;
     
                                 }
                                 const bruh2= DocListCast(this.Document.data).filter(doc => doc.title === 'line' || doc.title === 'stroke').map(doc => DocumentManager.Instance.getDocumentView(doc, this.DocumentView?.())).filter(inkView => inkView?.ComponentView instanceof InkingStroke).map(stroke => stroke?.ComponentView);
-- 
cgit v1.2.3-70-g09d2


From d509f24d29290cfc67d58a7a34c056ac1b163844 Mon Sep 17 00:00:00 2001
From: Zachary Zhang <zacharyzhang7@gmail.com>
Date: Mon, 24 Jun 2024 12:59:21 -0400
Subject: bug fixes + edit gpt generated code + unused code for line locking

---
 src/client/views/nodes/DiagramBox.scss |  11 ++++
 src/client/views/nodes/DiagramBox.tsx  | 102 +++++++++++++++++++++++----------
 2 files changed, 83 insertions(+), 30 deletions(-)

(limited to 'src/client/views/nodes/DiagramBox.tsx')

diff --git a/src/client/views/nodes/DiagramBox.scss b/src/client/views/nodes/DiagramBox.scss
index d73dd2a97..4bfd4f7cb 100644
--- a/src/client/views/nodes/DiagramBox.scss
+++ b/src/client/views/nodes/DiagramBox.scss
@@ -181,6 +181,17 @@
                     height:23px;
                     border-radius: 10px;
                 }
+                .rightButtons{
+                    display:flex;
+                    flex-direction: column;
+                    button {
+                        padding: 5px 10px;
+                        width:80px;
+                        height:23px;
+                        margin:2;
+                        border-radius: 10px;
+                    }
+                }
             }
             .loading-circle {
                 position: absolute;
diff --git a/src/client/views/nodes/DiagramBox.tsx b/src/client/views/nodes/DiagramBox.tsx
index fcf6e580b..6ea574aab 100644
--- a/src/client/views/nodes/DiagramBox.tsx
+++ b/src/client/views/nodes/DiagramBox.tsx
@@ -1,7 +1,7 @@
 /* eslint-disable prettier/prettier */
 /* eslint-disable jsx-a11y/control-has-associated-label */
 import mermaid from 'mermaid';
-import { action, makeObservable, observable, reaction } from 'mobx';
+import { action, makeObservable, observable, reaction, computed } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc, DocListCast } from '../../../fields/Doc';
@@ -70,23 +70,33 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         if (typeof this.Document.drawingMermaidCode === 'string' && this.Document.menuState === 'drawing') {
             this.renderMermaidAsync(this.Document.drawingMermaidCode);
         }
-        this.renderMermaidAsync(this.timeline);
         // this is so that ever time a new doc, text node or ink node, is created, this.createMermaidCode will run which will create a save
-        // reaction(
-        //     () => DocListCast(this.Document.data),
-        //     () => this.lockInkStroke(),
-        //     { fireImmediately: true }
+        reaction(
+            () => DocListCast(this.Document.data),
+            () => this.lockInkStroke(),
+            { fireImmediately: true }
+        );
+        reaction(
+            () =>
+                DocListCast(this.Document.data)
+                    .filter(doc => doc.type === 'rich text')
+                    .map(doc => (doc.text as RichTextField).Text),
+            () => this.convertDrawingToMermaidCode(),
+            { fireImmediately: true }
+        );
+        // const rectangleXValues = computed(() =>
+        //     DocListCast(this.Document.data)
+        //         .filter(doc => doc.title === 'rectangle')
+        //         .map(doc => doc.x)
         // );
         // reaction(
-        //     () =>
-        //         DocListCast(this.Document.data)
-        //             .filter(doc => doc.type === 'rich text')
-        //             .map(doc => (doc.text as RichTextField).Text),
-        //     () => this.convertDrawingToMermaidCode(),
+        //     () => rectangleXValues.get(),
+        //     () => this.lockInkStroke(),
         //     { fireImmediately: true }
         // );
-        this.lockInkStroke();
+         // this.lockInkStroke();
     }
+    
     componentDidUpdate = () => {
         if (typeof this.Document.drawingMermaidCode === 'string' && this.Document.menuState === 'drawing') {
             this.renderMermaidAsync(this.Document.drawingMermaidCode);
@@ -169,7 +179,6 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         this.loading = true;
         let prompt = '';
         prompt = 'Write this in mermaid code and only give me the mermaid code: ' + this.inputValue;
-        console.log('there is no text save');
         // }
         const res = await gptAPICall(prompt, GPTCallType.MERMAID);
         this.loading = true;
@@ -259,6 +268,8 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         }
     }
     async lockInkStroke() {
+        console.log("hello")
+        console.log(DocListCast(this.Document.data).filter(doc => doc.title === 'rectangle').map(doc => doc.x))
         if (this.Document.data instanceof List) {
             const docArray: Doc[] = DocListCast(this.Document.data);
             const rectangleArray = docArray.filter(doc => doc.title === 'rectangle' || doc.title === 'circle');
@@ -352,15 +363,14 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                     DocumentManager.Instance.AddViewRenderedCb(this.Document, (docViewForYourCollection) => {
                         if (docViewForYourCollection && docViewForYourCollection.ComponentView) {
                             if (docViewForYourCollection.ComponentView.addDocument&&docViewForYourCollection.ComponentView.removeDocument) {
-                                if(!inkToDelete.transformed){
-                                    docViewForYourCollection.ComponentView?.removeDocument(inkToDelete)
-                                    docViewForYourCollection.ComponentView?.addDocument(newInkDoc);
-                                    newInkDoc.transformed=false;
-    
-                                }
-                                const bruh2= DocListCast(this.Document.data).filter(doc => doc.title === 'line' || doc.title === 'stroke').map(doc => DocumentManager.Instance.getDocumentView(doc, this.DocumentView?.())).filter(inkView => inkView?.ComponentView instanceof InkingStroke).map(stroke => stroke?.ComponentView);
-                                console.log(bruh2)
-                                console.log((bruh2[0] as InkingStroke)?.inkScaledData())
+                                // docViewForYourCollection.ComponentView?.removeDocument(inkToDelete)
+                                // docViewForYourCollection.ComponentView?.addDocument(newInkDoc);
+                            
+
+                            
+                                // const bruh2= DocListCast(this.Document.data).filter(doc => doc.title === 'line' || doc.title === 'stroke').map(doc => DocumentManager.Instance.getDocumentView(doc, this.DocumentView?.())).filter(inkView => inkView?.ComponentView instanceof InkingStroke).map(stroke => stroke?.ComponentView);
+                                // console.log(bruh2)
+                                // console.log((bruh2[0] as InkingStroke)?.inkScaledData())
                             }
                         }
                     });    
@@ -476,10 +486,15 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                         <button className="backButton" type="button" onClick={this.optionButton}>
                             Back
                         </button>
-                        <textarea value={this.inputValue} placeholder="Enter GPT prompt" onChange={this.handleInputChange} />
-                        <button className="generateButton" type="button" onClick={this.handleRenderClick}>
-                            Generate
-                        </button>
+                        <textarea value={this.inputValue} placeholder="Enter GPT prompt" onChange={this.handleInputChange}onInput={e => this.autoResize(e.target as HTMLTextAreaElement)} />
+                        <div className="rightButtons">
+                            <button className="generateButton" type="button" onClick={this.handleRenderClick}>
+                                Generate
+                            </button>
+                            <button className="convertButton" type="button" onClick={this.handleConvertButton}>
+                                Edit
+                            </button>
+                        </div>
                     </div>
                     {this.mermaidCode ? (
                         <div id={'dashDiv' + this.Document.title} className="diagramBox" />
@@ -490,7 +505,27 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             </div>
         );
     }
-
+    handleConvertButton=()=>{
+        this.Document.menuState = 'mermaidCode';
+        if(typeof this.Document.gptMermaidCode==='string'){
+            this.createInputValue=this.removeFirstEmptyLine(this.Document.gptMermaidCode);
+            console.log(this.Document.gptMermaidCode)
+            this.renderMermaidAsync(this.Document.gptMermaidCode);
+        }
+    }
+    removeFirstEmptyLine(input: string): string {
+        const lines = input.split('\n');
+        let emptyLineRemoved = false;
+        const resultLines = lines.filter(line => {
+            if (!emptyLineRemoved && line.trim() === '') {
+                emptyLineRemoved = true;
+                return false;
+            }
+            return true;
+        });
+        return resultLines.join('\n');
+    }
+    
     renderMermaidCode(): React.ReactNode {
         return (
             <div ref={this._dragRef} className="DiagramBox-wrapper">
@@ -522,7 +557,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                             </button>
                         </div>
                     )}
-                    <textarea value={this.createInputValue} placeholder="Enter Mermaid Code" onChange={this.handleInputChangeEditor} />
+                    <textarea value={this.createInputValue} placeholder="Enter Mermaid Code" onChange={this.handleInputChangeEditor}/>
                     <div id={'dashDiv' + this.Document.title} className="diagramBox" />
                 </div>
             </div>
@@ -541,14 +576,14 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         B --> C{Let me think}
         C -->|One| D[Laptop]
         C -->|Two| E[iPhone]
-        C -->|Three| F[fa:fa-car Car]`;
+        C -->|Three| F[fa:fa-car Car]`
         this.renderMermaidAsync(this.createInputValue);
     };
     pieButton = () => {
         this.createInputValue = `pie title Pets adopted by volunteers
         "Dogs" : 386
         "Cats" : 85
-        "Rats" : 15`;
+        "Rats" : 15`
         this.renderMermaidAsync(this.createInputValue);
     };
     timelineButton = () => {
@@ -613,6 +648,13 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             this.renderMermaidAsync(e.target.value);
         }
     };
+    removeWhitespace(str: string): string {
+        return str.replace(/\s+/g, '');
+    }
+    autoResize(element: HTMLTextAreaElement): void {
+        element.style.height = '5px';
+        element.style.height = element.scrollHeight + 'px';
+    }
     timeline = `gantt
     title College Timeline
     dateFormat  YYYY-MM-DD
-- 
cgit v1.2.3-70-g09d2


From 5d0dd1de740a8e1fa589ebf7dc7a9f7df0db63b9 Mon Sep 17 00:00:00 2001
From: Zachary Zhang <zacharyzhang7@gmail.com>
Date: Mon, 8 Jul 2024 12:52:54 -0400
Subject: switched to iink-ts not functional

---
 package-lock.json                                  |  14 +
 package.json                                       |   1 +
 src/client/cognitive_services/CognitiveServices.ts |  11 +-
 src/client/documents/Documents.ts                  |   2 +-
 src/client/views/DocumentDecorations.tsx           |  13 +-
 src/client/views/InkTranscription.tsx              | 687 ++++++++++-----------
 src/client/views/InkingStroke.tsx                  |   4 +-
 src/client/views/MainView.tsx                      |   2 +
 src/client/views/global/globalScripts.ts           |   8 +-
 src/client/views/nodes/DiagramBox.tsx              |  32 +-
 src/client/views/nodes/ScreenshotBox.tsx           |   2 +-
 11 files changed, 398 insertions(+), 378 deletions(-)

(limited to 'src/client/views/nodes/DiagramBox.tsx')

diff --git a/package-lock.json b/package-lock.json
index b143dc5c1..9baf9b83a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -126,6 +126,7 @@
                 "https": "^1.0.0",
                 "https-browserify": "^1.0.0",
                 "i": "^0.3.7",
+                "iink-ts": "^1.0.5",
                 "image-data-uri": "^2.0.1",
                 "image-size": "^1.0.2",
                 "image-size-stream": "^1.1.0",
@@ -21626,6 +21627,14 @@
             "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
             "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA=="
         },
+        "node_modules/iink-ts": {
+            "version": "1.0.5",
+            "resolved": "https://registry.npmjs.org/iink-ts/-/iink-ts-1.0.5.tgz",
+            "integrity": "sha512-LAWWPvgcsLtouI9ExVijZbPGIWMfJtVCcuznbIDyboaPb+cHYsftcuJdjDU7TQwIpGP4hmcjNQA57XPCw4MK2A==",
+            "dependencies": {
+                "json-css": "^1.5.6"
+            }
+        },
         "node_modules/image-data-uri": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/image-data-uri/-/image-data-uri-2.0.1.tgz",
@@ -23231,6 +23240,11 @@
             "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
             "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="
         },
+        "node_modules/json-css": {
+            "version": "1.5.6",
+            "resolved": "https://registry.npmjs.org/json-css/-/json-css-1.5.6.tgz",
+            "integrity": "sha512-B/0T0OxZH9tSb93tXV6VOYtXqrPz/Vgz2QrCT/4NXen8HGElYkYr9V+8IrSVTMj/ftxa8cG1kcu7f3iAMlaFlQ=="
+        },
         "node_modules/json-parse-even-better-errors": {
             "version": "2.3.1",
             "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
diff --git a/package.json b/package.json
index 52f627b63..45c2458fb 100644
--- a/package.json
+++ b/package.json
@@ -211,6 +211,7 @@
         "https": "^1.0.0",
         "https-browserify": "^1.0.0",
         "i": "^0.3.7",
+        "iink-ts": "^1.0.5",
         "image-data-uri": "^2.0.1",
         "image-size": "^1.0.2",
         "image-size-stream": "^1.1.0",
diff --git a/src/client/cognitive_services/CognitiveServices.ts b/src/client/cognitive_services/CognitiveServices.ts
index 9808b6a01..9f46b8685 100644
--- a/src/client/cognitive_services/CognitiveServices.ts
+++ b/src/client/cognitive_services/CognitiveServices.ts
@@ -46,14 +46,15 @@ export enum Confidence {
 export namespace CognitiveServices {
     const ExecuteQuery = async <D>(service: Service, manager: APIManager<D>, data: D): Promise<any> => {
         const apiKey = process.env[service.toUpperCase()];
-        if (!apiKey) {
+        if (apiKey) {
+            console.log(data)
             console.log(`No API key found for ${service}: ensure youe root directory has .env file with _CLIENT_${service.toUpperCase()}.`);
             return undefined;
         }
 
         let results: any;
         try {
-            results = await manager.requester(apiKey, manager.converter(data), service).then(json => JSON.parse(json));
+            results = await manager.requester("has", manager.converter(data), service).then(json => JSON.parse(json));
         } catch (e) {
             throw e;
         }
@@ -137,6 +138,12 @@ export namespace CognitiveServices {
                     points: points.map(({ X: x, Y: y }) => `${x},${y}`).join(','),
                     language: 'en-US',
                 }));
+                console.log(JSON.stringify({
+                    version: 1,
+                    language: 'en-US',
+                    unit: 'mm',
+                    strokes,
+                }))
                 return JSON.stringify({
                     version: 1,
                     language: 'en-US',
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index a67e6b4f6..c2e201f52 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -767,7 +767,7 @@ export namespace Docs {
         export function ComparisonDocument(text: string, options: DocumentOptions = { title: 'Comparison Box' }) {
             return InstanceFromProto(Prototypes.get(DocumentType.COMPARISON), text, options);
         }
-        export function DiagramDocument(options: DocumentOptions = { title: 'bruh box' }) {
+        export function DiagramDocument(options: DocumentOptions = { title: '' }) {
             return InstanceFromProto(Prototypes.get(DocumentType.DIAGRAM), undefined, options);
         }
 
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 93c3e3338..96ce181f8 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -152,18 +152,25 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
     onContainerDown = (e: React.PointerEvent) => {
         const effectiveLayoutAcl = GetEffectiveAcl(DocumentView.Selected()[0].Document);
         if (effectiveLayoutAcl === AclAdmin || effectiveLayoutAcl === AclEdit || effectiveLayoutAcl === AclAugment) {
-            setupMoveUpEvents(this, e, moveEv => this.onBackgroundMove(true, moveEv), emptyFunction, emptyFunction);
+            setupMoveUpEvents(this, e, moveEv => {this.onBackgroundMove(true, moveEv)
+                console.log("im being moved ink")
+                return false;
+            }, emptyFunction, emptyFunction);
             e.stopPropagation();
         }
     };
 
     onTitleDown = (e: React.PointerEvent) => {
+        console.log("im clicked")
         const effectiveLayoutAcl = GetEffectiveAcl(DocumentView.SelectedDocs()[0]);
         if (effectiveLayoutAcl === AclAdmin || effectiveLayoutAcl === AclEdit || effectiveLayoutAcl === AclAugment) {
             setupMoveUpEvents(
                 this,
                 e,
-                moveEv => this.onBackgroundMove(true, moveEv),
+                moveEv => {this.onBackgroundMove(true, moveEv)
+                    console.log("im being dragged")
+                    return false;
+                },
                 emptyFunction,
                 action(() => {
                     const selected = DocumentView.SelectedDocs().length === 1 ? DocumentView.SelectedDocs()[0] : undefined;
@@ -182,7 +189,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
     };
     @action
     onBackgroundMove = (dragTitle: boolean, e: PointerEvent): boolean => {
-        const dragDocView = DocumentView.Selected()[0];
+        const dragDocView = DocumentView.Selected()[0];``
         const effectiveLayoutAcl = GetEffectiveAcl(dragDocView.Document);
         if (effectiveLayoutAcl !== AclAdmin && effectiveLayoutAcl !== AclEdit && effectiveLayoutAcl !== AclAugment) {
             return false;
diff --git a/src/client/views/InkTranscription.tsx b/src/client/views/InkTranscription.tsx
index 1ed8de1be..495bb6b83 100644
--- a/src/client/views/InkTranscription.tsx
+++ b/src/client/views/InkTranscription.tsx
@@ -1,349 +1,338 @@
-// import * as iink from 'iink-js';
-// import { action, observable } from 'mobx';
-// import * as React from 'react';
-// import { Doc, DocListCast } from '../../fields/Doc';
-// import { InkData, InkField, InkTool } from '../../fields/InkField';
-// import { Cast, DateCast, NumCast } from '../../fields/Types';
-// import { aggregateBounds } from '../../Utils';
-// import { DocumentType } from '../documents/DocumentTypes';
-// import { CollectionFreeFormView } from './collections/collectionFreeForm';
-// import { InkingStroke } from './InkingStroke';
-// import './InkTranscription.scss';
-
-// /**
-//  * Class component that handles inking in writing mode
-//  */
-// export class InkTranscription extends React.Component {
-//     static Instance: InkTranscription;
-
-//     @observable _mathRegister: any= undefined;
-//     @observable _mathRef: any= undefined;
-//     @observable _textRegister: any= undefined;
-//     @observable _textRef: any= undefined;
-//     private lastJiix: any;
-//     private currGroup?: Doc;
-
-//     constructor(props: Readonly<{}>) {
-//         super(props);
-
-//         InkTranscription.Instance = this;
-//     }
-
-//     componentWillUnmount() {
-//         this._mathRef.removeEventListener('exported', (e: any) => this.exportInk(e, this._mathRef));
-//         this._textRef.removeEventListener('exported', (e: any) => this.exportInk(e, this._textRef));
-//     }
-
-//     @action
-//     setMathRef = (r: any) => {
-//         if (!this._mathRegister) {
-//             this._mathRegister = r
-//                 ? iink.register(r, {
-//                       recognitionParams: {
-//                           type: 'MATH',
-//                           protocol: 'WEBSOCKET',
-//                           server: {
-//                               host: 'cloud.myscript.com',
-//                               applicationKey: process.env.IINKJS_APP,
-//                               hmacKey: process.env.IINKJS_HMAC,
-//                               websocket: {
-//                                   pingEnabled: false,
-//                                   autoReconnect: true,
-//                               },
-//                           },
-//                           iink: {
-//                               math: {
-//                                   mimeTypes: ['application/x-latex', 'application/vnd.myscript.jiix'],
-//                               },
-//                               export: {
-//                                   jiix: {
-//                                       strokes: true,
-//                                   },
-//                               },
-//                           },
-//                       },
-//                   })
-//                 : null;
-//         }
-
-//         r?.addEventListener('exported', (e: any) => this.exportInk(e, this._mathRef));
-
-//         return (this._mathRef = r);
-//     };
-
-//     @action
-//     setTextRef = (r: any) => {
-//         if (!this._textRegister) {
-//             this._textRegister = r
-//                 ? iink.register(r, {
-//                       recognitionParams: {
-//                           type: 'TEXT',
-//                           protocol: 'WEBSOCKET',
-//                           server: {
-//                               host: 'cloud.myscript.com',
-//                               applicationKey: '7277ec34-0c2e-4ee1-9757-ccb657e3f89f',
-//                               hmacKey: 'f5cb18f2-1f95-4ddb-96ac-3f7c888dffc1',
-//                               websocket: {
-//                                   pingEnabled: false,
-//                                   autoReconnect: true,
-//                               },
-//                           },
-//                           iink: {
-//                               text: {
-//                                   mimeTypes: ['text/plain'],
-//                               },
-//                               export: {
-//                                   jiix: {
-//                                       strokes: true,
-//                                   },
-//                               },
-//                           },
-//                       },
-//                   })
-//                 : null;
-//         }
-
-//         r?.addEventListener('exported', (e: any) => this.exportInk(e, this._textRef));
-
-//         return (this._textRef = r);
-//     };
-
-//     /**
-//      * Handles processing Dash Doc data for ink transcription.
-//      *
-//      * @param groupDoc the group which contains the ink strokes we want to transcribe
-//      * @param inkDocs the ink docs contained within the selected group
-//      * @param math boolean whether to do math transcription or not
-//      */
-//     transcribeInk = (groupDoc: Doc | undefined, inkDocs: Doc[], math: boolean) => {
-//         if (!groupDoc) return;
-//         const validInks = inkDocs.filter(s => s.type === DocumentType.INK);
-
-//         const strokes: InkData[] = [];
-//         const times: number[] = [];
-//         validInks
-//             .filter(i => Cast(i[Doc.LayoutFieldKey(i)], InkField))
-//             .forEach(i => {
-//                 const d = Cast(i[Doc.LayoutFieldKey(i)], InkField, null);
-//                 const inkStroke = DocumentManager.Instance.getDocumentView(i)?.ComponentView as InkingStroke;
-//                 strokes.push(d.inkData.map(pd => inkStroke.ptToScreen({ X: pd.X, Y: pd.Y })));
-//                 times.push(DateCast(i.author_date).getDate().getTime());
-//             });
-
-//         this.currGroup = groupDoc;
-
-//         const pointerData = { events: strokes.map((stroke, i) => this.inkJSON(stroke, times[i])) };
-//         const processGestures = false;
-
-//         if (math) {
-//             this._mathRef.editor.pointerEvents(pointerData, processGestures);
-//         } else {
-//             this._textRef.editor.pointerEvents(pointerData, processGestures);
-//         }
-//     };
-
-//     /**
-//      * Converts the Dash Ink Data to JSON.
-//      *
-//      * @param stroke The dash ink data
-//      * @param time the time of the stroke
-//      * @returns json object representation of ink data
-//      */
-//     inkJSON = (stroke: InkData, time: number) => {
-//         return {
-//             pointerType: 'PEN',
-//             pointerId: 1,
-//             x: stroke.map(point => point.X),
-//             y: stroke.map(point => point.Y),
-//             t: new Array(stroke.length).fill(time),
-//             p: new Array(stroke.length).fill(1.0),
-//         };
-//     };
-
-//     /**
-//      * Creates subgroups for each word for the whole text transcription
-//      * @param wordInkDocMap the mapping of words to ink strokes (Ink Docs)
-//      */
-//     subgroupsTranscriptions = (wordInkDocMap: Map<string, Doc[]>) => {
-//         // iterate through the keys of wordInkDocMap
-//         wordInkDocMap.forEach(async (inkDocs: Doc[], word: string) => {
-//             const selected = inkDocs.slice();
-//             if (!selected) {
-//                 return;
-//             }
-//             const ctx = await Cast(selected[0].embedContainer, Doc);
-//             if (!ctx) {
-//                 return;
-//             }
-//             const docView: CollectionFreeFormView = DocumentManager.Instance.getDocumentView(ctx)?.ComponentView as CollectionFreeFormView;
-
-//             if (!docView) return;
-//             const marqViewRef = docView._marqueeViewRef.current;
-//             if (!marqViewRef) return;
-//             this.groupInkDocs(selected, docView, word);
-//         });
-//     };
-
-//     /**
-//      * Event listener function for when the 'exported' event is heard.
-//      *
-//      * @param e the event objects
-//      * @param ref the ref to the editor
-//      */
-//     exportInk = (e: any, ref: any) => {
-//         const exports = e.detail.exports;
-//         if (exports) {
-//             if (exports['application/x-latex']) {
-//                 const latex = exports['application/x-latex'];
-//                 if (this.currGroup) {
-//                     this.currGroup.text = latex;
-//                     this.currGroup.title = latex;
-//                 }
-
-//                 ref.editor.clear();
-//             } else if (exports['text/plain']) {
-//                 if (exports['application/vnd.myscript.jiix']) {
-//                     this.lastJiix = JSON.parse(exports['application/vnd.myscript.jiix']);
-//                     // map timestamp to strokes
-//                     const timestampWord = new Map<number, string>();
-//                     this.lastJiix.words.map((word: any) => {
-//                         if (word.items) {
-//                             word.items.forEach((i: { id: string; timestamp: string; X: Array<number>; Y: Array<number>; F: Array<number> }) => {
-//                                 const ms = Date.parse(i.timestamp);
-//                                 timestampWord.set(ms, word.label);
-//                             });
-//                         }
-//                     });
-
-//                     const wordInkDocMap = new Map<string, Doc[]>();
-//                     if (this.currGroup) {
-//                         const docList = DocListCast(this.currGroup.data);
-//                         docList.forEach((inkDoc: Doc) => {
-//                             // just having the times match up and be a unique value (actual timestamp doesn't matter)
-//                             const ms = DateCast(inkDoc.author_date).getDate().getTime() + 14400000;
-//                             const word = timestampWord.get(ms);
-//                             if (!word) {
-//                                 return;
-//                             }
-//                             const entry = wordInkDocMap.get(word);
-//                             if (entry) {
-//                                 entry.push(inkDoc);
-//                                 wordInkDocMap.set(word, entry);
-//                             } else {
-//                                 const newEntry = [inkDoc];
-//                                 wordInkDocMap.set(word, newEntry);
-//                             }
-//                         });
-//                         if (this.lastJiix.words.length > 1) this.subgroupsTranscriptions(wordInkDocMap);
-//                     }
-//                 }
-//                 const text = exports['text/plain'];
-
-//                 if (this.currGroup) {
-//                     this.currGroup.transcription = text;
-//                     this.currGroup.title = text.split('\n')[0];
-//                 }
-
-//                 ref.editor.clear();
-//             }
-//         }
-//     };
-
-//     /**
-//      * Creates the ink grouping once the user leaves the writing mode.
-//      */
-//     createInkGroup() {
-//         // TODO nda - if document being added to is a inkGrouping then we can just add to that group
-//         if (Doc.ActiveTool === InkTool.Write) {
-//             CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => {
-//                 // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those
-//                 const selected = ffView.unprocessedDocs;
-//                 const newCollection = this.groupInkDocs(
-//                     selected.filter(doc => doc.embedContainer),
-//                     ffView
-//                 );
-//                 ffView.unprocessedDocs = [];
-
-//                 InkTranscription.Instance.transcribeInk(newCollection, selected, false);
-//             });
-//         }
-//         CollectionFreeFormView.collectionsWithUnprocessedInk.clear();
-//     }
-
-//     /**
-//      * Creates the groupings for a given list of ink docs on a specific doc view
-//      * @param selected: the list of ink docs to create a grouping of
-//      * @param docView: the view in which we want the grouping to be created
-//      * @param word: optional param if the group we are creating is a word (subgrouping individual words)
-//      * @returns a new collection Doc or undefined if the grouping fails
-//      */
-//     groupInkDocs(selected: Doc[], docView: CollectionFreeFormView, word?: string): Doc | undefined {
-//         const bounds: { x: number; y: number; width?: number; height?: number }[] = [];
-
-//         // calculate the necessary bounds from the selected ink docs
-//         selected.map(
-//             action(d => {
-//                 const x = NumCast(d.x);
-//                 const y = NumCast(d.y);
-//                 const width = NumCast(d._width);
-//                 const height = NumCast(d._height);
-//                 bounds.push({ x, y, width, height });
-//             })
-//         );
-
-//         // calculate the aggregated bounds
-//         const aggregBounds = aggregateBounds(bounds, 0, 0);
-//         const marqViewRef = docView._marqueeViewRef.current;
-
-//         // set the vals for bounds in marqueeView
-//         if (marqViewRef) {
-//             marqViewRef._downX = aggregBounds.x;
-//             marqViewRef._downY = aggregBounds.y;
-//             marqViewRef._lastX = aggregBounds.r;
-//             marqViewRef._lastY = aggregBounds.b;
-//         }
-
-//         // map through all the selected ink strokes and create the groupings
-//         selected.map(
-//             action(d => {
-//                 const dx = NumCast(d.x);
-//                 const dy = NumCast(d.y);
-//                 delete d.x;
-//                 delete d.y;
-//                 delete d.activeFrame;
-//                 delete d._timecodeToShow; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection
-//                 delete d._timecodeToHide; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection
-//                 // calculate pos based on bounds
-//                 if (marqViewRef?.Bounds) {
-//                     d.x = dx - marqViewRef.Bounds.left - marqViewRef.Bounds.width / 2;
-//                     d.y = dy - marqViewRef.Bounds.top - marqViewRef.Bounds.height / 2;
-//                 }
-//                 return d;
-//             })
-//         );
-//         docView.props.removeDocument?.(selected);
-//         // Gets a collection based on the selected nodes using a marquee view ref
-//         const newCollection = marqViewRef?.getCollection(selected, undefined, true);
-//         if (newCollection) {
-//             newCollection.width = NumCast(newCollection._width);
-//             newCollection.height = NumCast(newCollection._height);
-//             // if the grouping we are creating is an individual word
-//             if (word) {
-//                 newCollection.title = word;
-//             }
-//         }
-
-//         // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs
-//         newCollection && docView.props.addDocument?.(newCollection);
-//         return newCollection;
-//     }
-
-//     render() {
-//         return (
-//             <div className="ink-transcription">
-//                 <div className="math-editor" ref={this.setMathRef} touch-action="none"></div>
-//                 <div className="text-editor" ref={this.setTextRef} touch-action="none"></div>
-//             </div>
-//         );
-//     }
-// }
+import * as iink from 'iink-ts';
+import {TProtocol,TSchene,TServerConfiguration,TConfiguration,TRecognitionConfiguration} from 'iink-ts';
+import { action, observable } from 'mobx';
+import * as React from 'react';
+import { Doc, DocListCast } from '../../fields/Doc';
+import { InkData, InkField, InkTool } from '../../fields/InkField';
+import { Cast, DateCast, NumCast } from '../../fields/Types';
+import { aggregateBounds } from '../../Utils';
+import { DocumentType } from '../documents/DocumentTypes';
+import { CollectionFreeFormView } from './collections/collectionFreeForm';
+import { InkingStroke } from './InkingStroke';
+import './InkTranscription.scss';
+import { DocumentView } from './nodes/DocumentView';
+
+/**
+ * Class component that handles inking in writing mode
+ */
+export class InkTranscription extends React.Component {
+    static Instance: InkTranscription;
+
+    @observable _mathRegister: any= undefined;
+    @observable _mathRef: any= undefined;
+    @observable _textRegister: any= undefined;
+    @observable _textRef: any= undefined;
+    private lastJiix: any;
+    private currGroup?: Doc;
+
+    constructor(props: Readonly<{}>) {
+        super(props);
+
+        InkTranscription.Instance = this;
+    }
+
+    componentWillUnmount() {
+        // this._mathRef.removeEventListener('exported', (e: any) => this.exportInk(e, this._mathRef));
+        // this._textRef.removeEventListener('exported', (e: any) => this.exportInk(e, this._textRef));
+    }
+
+    @action
+    setMathRef = async (r: any) => {
+        if (!this._textRegister && r) {
+            let editor;
+            const options = {
+                configuration: {
+                    server: {
+                        scheme: "https",
+                        host: "cloud.myscript.com",
+                        applicationKey: "c0901093-5ac5-4454-8e64-0def0f13f2ca",
+                        hmacKey: "f6465cca-1856-4492-a6a4-e2395841be2f",
+                        protocol: "WEBSOCKET"
+                    },
+                    recognition: {
+                        type: "TEXT",
+                    }
+                }
+            };
+            
+            editor = new iink.Editor(r, options as any);
+            
+            await editor.initialize();
+            
+            this._textRegister = r;
+            r?.addEventListener('exported', (e: any) => this.exportInk(e, this._textRef));
+
+            return (this._textRef = r);
+        }
+    }
+    @action
+    setTextRef = async (r:any) => {
+        if (!this._textRegister && r) {
+            let editor;
+            const options = {
+                configuration: {
+                    server: {
+                        scheme: "https",
+                        host: "cloud.myscript.com",
+                        applicationKey: "c0901093-5ac5-4454-8e64-0def0f13f2ca",
+                        hmacKey: "f6465cca-1856-4492-a6a4-e2395841be2f",
+                        protocol: "WEBSOCKET"
+                    },
+                    recognition: {
+                        type: "TEXT",
+                    }
+                }
+            };
+            
+            editor = new iink.Editor(r, options as any);
+            
+            await editor.initialize();
+            
+            this._textRegister = r;
+            r?.addEventListener('exported', (e: any) => this.exportInk(e, this._textRef));
+
+            return (this._textRef = r);
+        }
+        
+    };
+
+    /**
+     * Handles processing Dash Doc data for ink transcription.
+     *
+     * @param groupDoc the group which contains the ink strokes we want to transcribe
+     * @param inkDocs the ink docs contained within the selected group
+     * @param math boolean whether to do math transcription or not
+     */
+    transcribeInk = (groupDoc: Doc | undefined, inkDocs: Doc[], math: boolean) => {
+        if (!groupDoc) return;
+        const validInks = inkDocs.filter(s => s.type === DocumentType.INK);
+
+        const strokes: InkData[] = [];
+        const times: number[] = [];
+        validInks
+            .filter(i => Cast(i[Doc.LayoutFieldKey(i)], InkField))
+            .forEach(i => {
+                const d = Cast(i[Doc.LayoutFieldKey(i)], InkField, null);
+                const inkStroke = DocumentView.getDocumentView(i)?.ComponentView as InkingStroke;
+                strokes.push(d.inkData.map(pd => inkStroke.ptToScreen({ X: pd.X, Y: pd.Y })));
+                times.push(DateCast(i.author_date).getDate().getTime());
+            });
+
+        this.currGroup = groupDoc;
+
+        const pointerData = { events: strokes.map((stroke, i) => this.inkJSON(stroke, times[i])) };
+        const processGestures = false;
+
+        if (math) {
+            this._mathRef.editor.pointerEvents(pointerData, processGestures);
+        } else {
+            this._textRef.editor.pointerEvents(pointerData, processGestures);
+        }
+    };
+
+    /**
+     * Converts the Dash Ink Data to JSON.
+     *
+     * @param stroke The dash ink data
+     * @param time the time of the stroke
+     * @returns json object representation of ink data
+     */
+    inkJSON = (stroke: InkData, time: number) => {
+        return {
+            pointerType: 'PEN',
+            pointerId: 1,
+            x: stroke.map(point => point.X),
+            y: stroke.map(point => point.Y),
+            t: new Array(stroke.length).fill(time),
+            p: new Array(stroke.length).fill(1.0),
+        };
+    };
+
+    /**
+     * Creates subgroups for each word for the whole text transcription
+     * @param wordInkDocMap the mapping of words to ink strokes (Ink Docs)
+     */
+    subgroupsTranscriptions = (wordInkDocMap: Map<string, Doc[]>) => {
+        // iterate through the keys of wordInkDocMap
+        wordInkDocMap.forEach(async (inkDocs: Doc[], word: string) => {
+            const selected = inkDocs.slice();
+            if (!selected) {
+                return;
+            }
+            const ctx = await Cast(selected[0].embedContainer, Doc);
+            if (!ctx) {
+                return;
+            }
+            const docView: CollectionFreeFormView =DocumentView.getDocumentView(ctx)?.ComponentView as CollectionFreeFormView;
+            // DocumentManager.Instance.getDocumentView(ctx)?.ComponentView as CollectionFreeFormView;
+
+            if (!docView) return;
+            const marqViewRef = docView._marqueeViewRef.current;
+            if (!marqViewRef) return;
+            this.groupInkDocs(selected, docView, word);
+        });
+    };
+
+    /**
+     * Event listener function for when the 'exported' event is heard.
+     *
+     * @param e the event objects
+     * @param ref the ref to the editor
+     */
+    exportInk = (e: any, ref: any) => {
+        const exports = e.detail.exports;
+        if (exports) {
+            if (exports['application/x-latex']) {
+                const latex = exports['application/x-latex'];
+                if (this.currGroup) {
+                    this.currGroup.text = latex;
+                    this.currGroup.title = latex;
+                }
+
+                ref.editor.clear();
+            } else if (exports['text/plain']) {
+                if (exports['application/vnd.myscript.jiix']) {
+                    this.lastJiix = JSON.parse(exports['application/vnd.myscript.jiix']);
+                    // map timestamp to strokes
+                    const timestampWord = new Map<number, string>();
+                    this.lastJiix.words.map((word: any) => {
+                        if (word.items) {
+                            word.items.forEach((i: { id: string; timestamp: string; X: Array<number>; Y: Array<number>; F: Array<number> }) => {
+                                const ms = Date.parse(i.timestamp);
+                                timestampWord.set(ms, word.label);
+                            });
+                        }
+                    });
+
+                    const wordInkDocMap = new Map<string, Doc[]>();
+                    if (this.currGroup) {
+                        const docList = DocListCast(this.currGroup.data);
+                        docList.forEach((inkDoc: Doc) => {
+                            // just having the times match up and be a unique value (actual timestamp doesn't matter)
+                            const ms = DateCast(inkDoc.author_date).getDate().getTime() + 14400000;
+                            const word = timestampWord.get(ms);
+                            if (!word) {
+                                return;
+                            }
+                            const entry = wordInkDocMap.get(word);
+                            if (entry) {
+                                entry.push(inkDoc);
+                                wordInkDocMap.set(word, entry);
+                            } else {
+                                const newEntry = [inkDoc];
+                                wordInkDocMap.set(word, newEntry);
+                            }
+                        });
+                        if (this.lastJiix.words.length > 1) this.subgroupsTranscriptions(wordInkDocMap);
+                    }
+                }
+                const text = exports['text/plain'];
+
+                if (this.currGroup) {
+                    this.currGroup.transcription = text;
+                    this.currGroup.title = text.split('\n')[0];
+                }
+
+                ref.editor.clear();
+            }
+        }
+    };
+
+    /**
+     * Creates the ink grouping once the user leaves the writing mode.
+     */
+    createInkGroup() {
+        // TODO nda - if document being added to is a inkGrouping then we can just add to that group
+        if (Doc.ActiveTool === InkTool.Write) {
+            CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => {
+                // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those
+                const selected = ffView.unprocessedDocs;
+                const newCollection = this.groupInkDocs(
+                    selected.filter(doc => doc.embedContainer),
+                    ffView
+                );
+                ffView.unprocessedDocs = [];
+
+                InkTranscription.Instance.transcribeInk(newCollection, selected, false);
+            });
+        }
+        CollectionFreeFormView.collectionsWithUnprocessedInk.clear();
+    }
+
+    /**
+     * Creates the groupings for a given list of ink docs on a specific doc view
+     * @param selected: the list of ink docs to create a grouping of
+     * @param docView: the view in which we want the grouping to be created
+     * @param word: optional param if the group we are creating is a word (subgrouping individual words)
+     * @returns a new collection Doc or undefined if the grouping fails
+     */
+    groupInkDocs(selected: Doc[], docView: CollectionFreeFormView, word?: string): Doc | undefined {
+        const bounds: { x: number; y: number; width?: number; height?: number }[] = [];
+
+        // calculate the necessary bounds from the selected ink docs
+        selected.map(
+            action(d => {
+                const x = NumCast(d.x);
+                const y = NumCast(d.y);
+                const width = NumCast(d._width);
+                const height = NumCast(d._height);
+                bounds.push({ x, y, width, height });
+            })
+        );
+
+        // calculate the aggregated bounds
+        const aggregBounds = aggregateBounds(bounds, 0, 0);
+        const marqViewRef = docView._marqueeViewRef.current;
+
+        // set the vals for bounds in marqueeView
+        if (marqViewRef) {
+            marqViewRef._downX = aggregBounds.x;
+            marqViewRef._downY = aggregBounds.y;
+            marqViewRef._lastX = aggregBounds.r;
+            marqViewRef._lastY = aggregBounds.b;
+        }
+
+        // map through all the selected ink strokes and create the groupings
+        selected.map(
+            action(d => {
+                const dx = NumCast(d.x);
+                const dy = NumCast(d.y);
+                delete d.x;
+                delete d.y;
+                delete d.activeFrame;
+                delete d._timecodeToShow; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection
+                delete d._timecodeToHide; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection
+                // calculate pos based on bounds
+                if (marqViewRef?.Bounds) {
+                    d.x = dx - marqViewRef.Bounds.left - marqViewRef.Bounds.width / 2;
+                    d.y = dy - marqViewRef.Bounds.top - marqViewRef.Bounds.height / 2;
+                }
+                return d;
+            })
+        );
+        docView.props.removeDocument?.(selected);
+        // Gets a collection based on the selected nodes using a marquee view ref
+        const newCollection = marqViewRef?.getCollection(selected, undefined, true);
+        if (newCollection) {
+            newCollection.width = NumCast(newCollection._width);
+            newCollection.height = NumCast(newCollection._height);
+            // if the grouping we are creating is an individual word
+            if (word) {
+                newCollection.title = word;
+            }
+        }
+
+        // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs
+        newCollection && docView.props.addDocument?.(newCollection);
+        return newCollection;
+    }
+
+    render() {
+        return (
+            <div className="ink-transcription">
+                <div className="math-editor" ref={this.setMathRef} touch-action="none"></div>
+                <div className="text-editor" ref={this.setTextRef} touch-action="none"></div>
+            </div>
+        );
+    }
+}
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 55f28f415..ce1c07f2f 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -104,8 +104,8 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
      * analyzes the ink stroke and saves the analysis of the stroke to the 'inkAnalysis' field,
      * and the recognized words to the 'handwriting'
      */
-    analyzeStrokes() {
-        const data: InkData = Cast(this.dataDoc[this.fieldKey], InkField)?.inkData ?? [];
+    analyzeStrokes=()=> {
+        const data: InkData = this.inkScaledData().inkData ?? [];
         CognitiveServices.Inking.Appliers.ConcatenateHandwriting(this.dataDoc, ['inkAnalysis', 'handwriting'], [data]);
     }
 
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 31d88fb87..0dcf2fa79 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -76,6 +76,7 @@ import { PresBox } from './nodes/trails';
 import { AnchorMenu } from './pdf/AnchorMenu';
 import { GPTPopup } from './pdf/GPTPopup/GPTPopup';
 import { TopBar } from './topbar/TopBar';
+import { InkTranscription } from './InkTranscription';
 
 const { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } = require('./global/globalCssVariables.module.scss'); // prettier-ignore
 const _global = (window /* browser */ || global) /* node */ as any;
@@ -1096,6 +1097,7 @@ export class MainView extends ObservableReactComponent<{}> {
                 <MarqueeOptionsMenu />
                 <TimelineMenu />
                 <RichTextMenu />
+                <InkTranscription/>
                 {this.snapLines}
                 <LightboxView key="lightbox" PanelWidth={this._windowWidth} addSplit={CollectionDockingView.AddSplit} PanelHeight={this._windowHeight} maxBorder={this.lightboxMaxBorder} />
                 <GPTPopup key="gptpopup" />
diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts
index 7730ed385..83c0865f6 100644
--- a/src/client/views/global/globalScripts.ts
+++ b/src/client/views/global/globalScripts.ts
@@ -38,8 +38,7 @@ import { WebBox } from '../nodes/WebBox';
 import { RichTextMenu } from '../nodes/formattedText/RichTextMenu';
 import { NumListCast } from '../../../fields/Doc';
 import { List } from '../../../fields/List';
-
-// import { InkTranscription } from '../InkTranscription';
+import { InkTranscription } from '../InkTranscription';
 
 // eslint-disable-next-line prefer-arrow-callback
 ScriptingGlobals.add(function IsNoneSelected() {
@@ -367,6 +366,7 @@ ScriptingGlobals.add(function toggleCharStyle(charStyle: attrname, checkResult?:
 export function createInkGroup(/* inksToGroup?: Doc[], isSubGroup?: boolean */) {
     // TODO nda - if document being added to is a inkGrouping then we can just add to that group
     if (Doc.ActiveTool === InkTool.Write) {
+        console.log("create inking group ")
         CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => {
             // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those
             const selected = ffView.unprocessedDocs;
@@ -424,14 +424,14 @@ export function createInkGroup(/* inksToGroup?: Doc[], isSubGroup?: boolean */)
             // TODO: nda - will probably need to go through and only remove the unprocessed selected docs
             ffView.unprocessedDocs = [];
 
-            //  InkTranscription.Instance.transcribeInk(newCollection, selected, false);
+            InkTranscription.Instance.transcribeInk(newCollection, selected, false);
         });
     }
     CollectionFreeFormView.collectionsWithUnprocessedInk.clear();
 }
 
 function setActiveTool(tool: InkTool | Gestures, keepPrim: boolean, checkResult?: boolean) {
-    // InkTranscription.Instance?.createInkGroup();
+    //InkTranscription.Instance?.createInkGroup();
     if (checkResult) {
         return (Doc.ActiveTool === tool && !GestureOverlay.Instance?.InkShape) || GestureOverlay.Instance?.InkShape === tool
             ? GestureOverlay.Instance?.KeepPrimitiveMode || ![Gestures.Circle, Gestures.Line, Gestures.Rectangle].includes(tool as Gestures)
diff --git a/src/client/views/nodes/DiagramBox.tsx b/src/client/views/nodes/DiagramBox.tsx
index 6ea574aab..fcc028aab 100644
--- a/src/client/views/nodes/DiagramBox.tsx
+++ b/src/client/views/nodes/DiagramBox.tsx
@@ -71,19 +71,19 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             this.renderMermaidAsync(this.Document.drawingMermaidCode);
         }
         // this is so that ever time a new doc, text node or ink node, is created, this.createMermaidCode will run which will create a save
-        reaction(
-            () => DocListCast(this.Document.data),
-            () => this.lockInkStroke(),
-            { fireImmediately: true }
-        );
-        reaction(
-            () =>
-                DocListCast(this.Document.data)
-                    .filter(doc => doc.type === 'rich text')
-                    .map(doc => (doc.text as RichTextField).Text),
-            () => this.convertDrawingToMermaidCode(),
-            { fireImmediately: true }
-        );
+        // reaction(
+        //     () => DocListCast(this.Document.data),
+        //     () => this.lockInkStroke(),
+        //     { fireImmediately: true }
+        // );
+        // reaction(
+        //     () =>
+        //         DocListCast(this.Document.data)
+        //             .filter(doc => doc.type === 'rich text')
+        //             .map(doc => (doc.text as RichTextField).Text),
+        //     () => this.convertDrawingToMermaidCode(),
+        //     { fireImmediately: true }
+        // );
         // const rectangleXValues = computed(() =>
         //     DocListCast(this.Document.data)
         //         .filter(doc => doc.title === 'rectangle')
@@ -94,7 +94,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         //     () => this.lockInkStroke(),
         //     { fireImmediately: true }
         // );
-         // this.lockInkStroke();
+         this.lockInkStroke();
     }
     
     componentDidUpdate = () => {
@@ -363,8 +363,8 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                     DocumentManager.Instance.AddViewRenderedCb(this.Document, (docViewForYourCollection) => {
                         if (docViewForYourCollection && docViewForYourCollection.ComponentView) {
                             if (docViewForYourCollection.ComponentView.addDocument&&docViewForYourCollection.ComponentView.removeDocument) {
-                                // docViewForYourCollection.ComponentView?.removeDocument(inkToDelete)
-                                // docViewForYourCollection.ComponentView?.addDocument(newInkDoc);
+                                 docViewForYourCollection.ComponentView?.removeDocument(inkToDelete)
+                                 docViewForYourCollection.ComponentView?.addDocument(newInkDoc);
                             
 
                             
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index 3be50f5e6..e6590958b 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -149,7 +149,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
 
     componentDidMount() {
         this.dataDoc.nativeWidth = this.dataDoc.nativeHeight = 0;
-        this._props.setContentViewBox?.(this); // this tells the DocumentView that this ScreenshotBox is the "content" of the document.  this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link.
+        this._props.setContentViewBox?.(this); // this tells the DocumentView that this Box is the "content" of the document.  this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link.
         // this.layoutDoc.videoWall && reaction(() => ({ width: this._props.PanelWidth(), height: this._props.PanelHeight() }),
         //     ({ width, height }) => {
         //         if (this._camera) {
-- 
cgit v1.2.3-70-g09d2


From 74c9d7cb47281dab59908eea5384b370f493d087 Mon Sep 17 00:00:00 2001
From: Zachary Zhang <zacharyzhang7@gmail.com>
Date: Wed, 10 Jul 2024 13:29:50 -0400
Subject: work in progres

---
 src/client/views/DocumentDecorations.tsx |  15 +--
 src/client/views/InkTranscription.scss   |   5 +
 src/client/views/InkTranscription.tsx    | 138 ++++++++++++++++----------
 src/client/views/nodes/DiagramBox.tsx    | 162 ++++++++++++++++---------------
 4 files changed, 181 insertions(+), 139 deletions(-)

(limited to 'src/client/views/nodes/DiagramBox.tsx')

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 96ce181f8..a229b15db 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -152,25 +152,18 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
     onContainerDown = (e: React.PointerEvent) => {
         const effectiveLayoutAcl = GetEffectiveAcl(DocumentView.Selected()[0].Document);
         if (effectiveLayoutAcl === AclAdmin || effectiveLayoutAcl === AclEdit || effectiveLayoutAcl === AclAugment) {
-            setupMoveUpEvents(this, e, moveEv => {this.onBackgroundMove(true, moveEv)
-                console.log("im being moved ink")
-                return false;
-            }, emptyFunction, emptyFunction);
+            setupMoveUpEvents(this, e, moveEv => this.onBackgroundMove(true, moveEv), emptyFunction, emptyFunction);
             e.stopPropagation();
         }
     };
 
     onTitleDown = (e: React.PointerEvent) => {
-        console.log("im clicked")
         const effectiveLayoutAcl = GetEffectiveAcl(DocumentView.SelectedDocs()[0]);
         if (effectiveLayoutAcl === AclAdmin || effectiveLayoutAcl === AclEdit || effectiveLayoutAcl === AclAugment) {
             setupMoveUpEvents(
                 this,
                 e,
-                moveEv => {this.onBackgroundMove(true, moveEv)
-                    console.log("im being dragged")
-                    return false;
-                },
+                moveEv => this.onBackgroundMove(true, moveEv),
                 emptyFunction,
                 action(() => {
                     const selected = DocumentView.SelectedDocs().length === 1 ? DocumentView.SelectedDocs()[0] : undefined;
@@ -189,7 +182,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
     };
     @action
     onBackgroundMove = (dragTitle: boolean, e: PointerEvent): boolean => {
-        const dragDocView = DocumentView.Selected()[0];``
+        const dragDocView = DocumentView.Selected()[0];
         const effectiveLayoutAcl = GetEffectiveAcl(dragDocView.Document);
         if (effectiveLayoutAcl !== AclAdmin && effectiveLayoutAcl !== AclEdit && effectiveLayoutAcl !== AclAugment) {
             return false;
@@ -879,4 +872,4 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
             </div>
         );
     }
-}
+}
\ No newline at end of file
diff --git a/src/client/views/InkTranscription.scss b/src/client/views/InkTranscription.scss
index bbb0a1afa..18d6b8b10 100644
--- a/src/client/views/InkTranscription.scss
+++ b/src/client/views/InkTranscription.scss
@@ -2,4 +2,9 @@
     .error-msg {
         display: none !important;
     }
+    .ms-editor{
+        .smartguide{
+            top:1000px;
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/client/views/InkTranscription.tsx b/src/client/views/InkTranscription.tsx
index 495bb6b83..44b63e605 100644
--- a/src/client/views/InkTranscription.tsx
+++ b/src/client/views/InkTranscription.tsx
@@ -1,16 +1,19 @@
 import * as iink from 'iink-ts';
-import {TProtocol,TSchene,TServerConfiguration,TConfiguration,TRecognitionConfiguration} from 'iink-ts';
 import { action, observable } from 'mobx';
 import * as React from 'react';
 import { Doc, DocListCast } from '../../fields/Doc';
 import { InkData, InkField, InkTool } from '../../fields/InkField';
-import { Cast, DateCast, NumCast } from '../../fields/Types';
+import { Cast, DateCast, ImageCast, NumCast, StrCast } from '../../fields/Types';
 import { aggregateBounds } from '../../Utils';
 import { DocumentType } from '../documents/DocumentTypes';
 import { CollectionFreeFormView } from './collections/collectionFreeForm';
 import { InkingStroke } from './InkingStroke';
 import './InkTranscription.scss';
+import { Docs } from '../documents/Documents';
 import { DocumentView } from './nodes/DocumentView';
+import { Number } from 'mongoose';
+import { NumberArray } from 'd3';
+import { ImageField } from '../../fields/URLField';
 
 /**
  * Class component that handles inking in writing mode
@@ -18,12 +21,14 @@ import { DocumentView } from './nodes/DocumentView';
 export class InkTranscription extends React.Component {
     static Instance: InkTranscription;
 
-    @observable _mathRegister: any= undefined;
-    @observable _mathRef: any= undefined;
-    @observable _textRegister: any= undefined;
-    @observable _textRef: any= undefined;
+    @observable _mathRegister: any = undefined;
+    @observable _mathRef: any = undefined;
+    @observable _textRegister: any = undefined;
+    @observable _textRef: any = undefined;
+    @observable iinkEditor: any = undefined;
     private lastJiix: any;
     private currGroup?: Doc;
+    private collectionFreeForm?: CollectionFreeFormView;
 
     constructor(props: Readonly<{}>) {
         super(props);
@@ -43,57 +48,56 @@ export class InkTranscription extends React.Component {
             const options = {
                 configuration: {
                     server: {
-                        scheme: "https",
-                        host: "cloud.myscript.com",
-                        applicationKey: "c0901093-5ac5-4454-8e64-0def0f13f2ca",
-                        hmacKey: "f6465cca-1856-4492-a6a4-e2395841be2f",
-                        protocol: "WEBSOCKET"
+                        scheme: 'https',
+                        host: 'cloud.myscript.com',
+                        applicationKey: 'c0901093-5ac5-4454-8e64-0def0f13f2ca',
+                        hmacKey: 'f6465cca-1856-4492-a6a4-e2395841be2f',
+                        protocol: 'WEBSOCKET',
                     },
                     recognition: {
-                        type: "TEXT",
-                    }
-                }
+                        type: 'TEXT',
+                    },
+                },
             };
-            
+
             editor = new iink.Editor(r, options as any);
-            
+
             await editor.initialize();
-            
+
             this._textRegister = r;
             r?.addEventListener('exported', (e: any) => this.exportInk(e, this._textRef));
 
             return (this._textRef = r);
         }
-    }
+    };
     @action
-    setTextRef = async (r:any) => {
+    setTextRef = async (r: any) => {
         if (!this._textRegister && r) {
             let editor;
             const options = {
                 configuration: {
                     server: {
-                        scheme: "https",
-                        host: "cloud.myscript.com",
-                        applicationKey: "c0901093-5ac5-4454-8e64-0def0f13f2ca",
-                        hmacKey: "f6465cca-1856-4492-a6a4-e2395841be2f",
-                        protocol: "WEBSOCKET"
+                        scheme: 'https',
+                        host: 'cloud.myscript.com',
+                        applicationKey: 'c0901093-5ac5-4454-8e64-0def0f13f2ca',
+                        hmacKey: 'f6465cca-1856-4492-a6a4-e2395841be2f',
+                        protocol: 'WEBSOCKET',
                     },
                     recognition: {
-                        type: "TEXT",
-                    }
-                }
+                        type: 'TEXT',
+                    },
+                },
             };
-            
+
             editor = new iink.Editor(r, options as any);
-            
+
             await editor.initialize();
-            
+            this.iinkEditor = editor;
             this._textRegister = r;
             r?.addEventListener('exported', (e: any) => this.exportInk(e, this._textRef));
 
             return (this._textRef = r);
         }
-        
     };
 
     /**
@@ -119,14 +123,14 @@ export class InkTranscription extends React.Component {
             });
 
         this.currGroup = groupDoc;
-
-        const pointerData = { events: strokes.map((stroke, i) => this.inkJSON(stroke, times[i])) };
+        const pointerData = strokes.map((stroke, i) => this.inkJSON(stroke, times[i]));
+        console.log(JSON.stringify(pointerData));
         const processGestures = false;
-
         if (math) {
-            this._mathRef.editor.pointerEvents(pointerData, processGestures);
+            console.log('math');
+            this.iinkEditor.importPointEvents(pointerData);
         } else {
-            this._textRef.editor.pointerEvents(pointerData, processGestures);
+            this.iinkEditor.importPointEvents(pointerData);
         }
     };
 
@@ -138,13 +142,26 @@ export class InkTranscription extends React.Component {
      * @returns json object representation of ink data
      */
     inkJSON = (stroke: InkData, time: number) => {
+        interface strokeData {
+            x: number;
+            y: number;
+            t: number;
+            p: number;
+        }
+        let strokeObjects: strokeData[] = [];
+        stroke.forEach(point => {
+            let tempObject: strokeData = {
+                x: point.X,
+                y: point.Y,
+                t: time,
+                p: 1.0,
+            };
+            strokeObjects.push(tempObject);
+        });
         return {
             pointerType: 'PEN',
             pointerId: 1,
-            x: stroke.map(point => point.X),
-            y: stroke.map(point => point.Y),
-            t: new Array(stroke.length).fill(time),
-            p: new Array(stroke.length).fill(1.0),
+            pointers: strokeObjects,
         };
     };
 
@@ -163,7 +180,7 @@ export class InkTranscription extends React.Component {
             if (!ctx) {
                 return;
             }
-            const docView: CollectionFreeFormView =DocumentView.getDocumentView(ctx)?.ComponentView as CollectionFreeFormView;
+            const docView: CollectionFreeFormView = DocumentView.getDocumentView(ctx)?.ComponentView as CollectionFreeFormView;
             // DocumentManager.Instance.getDocumentView(ctx)?.ComponentView as CollectionFreeFormView;
 
             if (!docView) return;
@@ -179,10 +196,11 @@ export class InkTranscription extends React.Component {
      * @param e the event objects
      * @param ref the ref to the editor
      */
-    exportInk = (e: any, ref: any) => {
-        const exports = e.detail.exports;
+    exportInk = async (e: any, ref: any) => {
+        const exports = e.detail['application/vnd.myscript.jiix'];
+        console.log(exports);
         if (exports) {
-            if (exports['application/x-latex']) {
+            if (exports['type'] == 'Math') {
                 const latex = exports['application/x-latex'];
                 if (this.currGroup) {
                     this.currGroup.text = latex;
@@ -190,7 +208,7 @@ export class InkTranscription extends React.Component {
                 }
 
                 ref.editor.clear();
-            } else if (exports['text/plain']) {
+            } else if (exports['type'] == 'Text') {
                 if (exports['application/vnd.myscript.jiix']) {
                     this.lastJiix = JSON.parse(exports['application/vnd.myscript.jiix']);
                     // map timestamp to strokes
@@ -226,17 +244,33 @@ export class InkTranscription extends React.Component {
                         if (this.lastJiix.words.length > 1) this.subgroupsTranscriptions(wordInkDocMap);
                     }
                 }
-                const text = exports['text/plain'];
+                const text = exports['label'];
 
-                if (this.currGroup) {
+                if (this.currGroup && text) {
+                    DocumentView.getDocumentView(this.currGroup)?.ComponentView?.updateIcon?.();
+                    console.log(this.currGroup.icon);
                     this.currGroup.transcription = text;
-                    this.currGroup.title = text.split('\n')[0];
+                    this.currGroup.title = text;
+                    let image = await this.getIcon();
+                    console.log(this.currGroup.icon, image);
+                    if (!this.currGroup.hasTextBox) {
+                        const newDoc = Docs.Create.TextDocument(text, { title: '', x: this.currGroup.x as number, y: (this.currGroup.y as number) + (this.currGroup.height as number) });
+                        this.collectionFreeForm?.addDocument(newDoc);
+                        this.currGroup.hasTextBox = true;
+                    }
+                    ref.editor.clear();
                 }
-
-                ref.editor.clear();
             }
         }
     };
+    async getIcon() {
+        const docView = DocumentView.getDocumentView(this.currGroup);
+        if (docView) {
+            docView.ComponentView?.updateIcon?.();
+            return new Promise<ImageField | undefined>(res => setTimeout(() => res(ImageCast(docView.Document.icon)), 500));
+        }
+        return undefined;
+    }
 
     /**
      * Creates the ink grouping once the user leaves the writing mode.
@@ -267,6 +301,7 @@ export class InkTranscription extends React.Component {
      * @returns a new collection Doc or undefined if the grouping fails
      */
     groupInkDocs(selected: Doc[], docView: CollectionFreeFormView, word?: string): Doc | undefined {
+        this.collectionFreeForm = docView;
         const bounds: { x: number; y: number; width?: number; height?: number }[] = [];
 
         // calculate the necessary bounds from the selected ink docs
@@ -324,6 +359,9 @@ export class InkTranscription extends React.Component {
 
         // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs
         newCollection && docView.props.addDocument?.(newCollection);
+        if (newCollection) {
+            newCollection.hasTextBox = false;
+        }
         return newCollection;
     }
 
diff --git a/src/client/views/nodes/DiagramBox.tsx b/src/client/views/nodes/DiagramBox.tsx
index fcc028aab..5a712b8b0 100644
--- a/src/client/views/nodes/DiagramBox.tsx
+++ b/src/client/views/nodes/DiagramBox.tsx
@@ -7,14 +7,14 @@ import * as React from 'react';
 import { Doc, DocListCast } from '../../../fields/Doc';
 import { List } from '../../../fields/List';
 import { RichTextField } from '../../../fields/RichTextField';
-import { DocCast,BoolCast } from '../../../fields/Types';
+import { DocCast, BoolCast } from '../../../fields/Types';
 import { GPTCallType, gptAPICall } from '../../apis/gpt/GPT';
 import { DocumentType } from '../../documents/DocumentTypes';
 import { Docs } from '../../documents/Documents';
 import { DocumentManager } from '../../util/DocumentManager';
 import { LinkManager } from '../../util/LinkManager';
 import { ViewBoxAnnotatableComponent } from '../DocComponent';
-import { InkingStroke} from '../InkingStroke';
+import { InkingStroke } from '../InkingStroke';
 import './DiagramBox.scss';
 import { FieldView, FieldViewProps } from './FieldView';
 import { PointData } from '../../../pen-gestures/GestureTypes';
@@ -94,9 +94,9 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         //     () => this.lockInkStroke(),
         //     { fireImmediately: true }
         // );
-         this.lockInkStroke();
+        this.lockInkStroke();
     }
-    
+
     componentDidUpdate = () => {
         if (typeof this.Document.drawingMermaidCode === 'string' && this.Document.menuState === 'drawing') {
             this.renderMermaidAsync(this.Document.drawingMermaidCode);
@@ -268,13 +268,17 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         }
     }
     async lockInkStroke() {
-        console.log("hello")
-        console.log(DocListCast(this.Document.data).filter(doc => doc.title === 'rectangle').map(doc => doc.x))
+        console.log('hello');
+        console.log(
+            DocListCast(this.Document.data)
+                .filter(doc => doc.title === 'rectangle')
+                .map(doc => doc.x)
+        );
         if (this.Document.data instanceof List) {
             const docArray: Doc[] = DocListCast(this.Document.data);
             const rectangleArray = docArray.filter(doc => doc.title === 'rectangle' || doc.title === 'circle');
-            if(rectangleArray[0]){
-                console.log(rectangleArray[0].x)
+            if (rectangleArray[0]) {
+                console.log(rectangleArray[0].x);
             }
             const lineArray = docArray.filter(doc => doc.title === 'line' || doc.title === 'stroke');
             const timeoutPromise = () =>
@@ -302,88 +306,90 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                 const startY = inkStrokeYArray[0] - minY + (lineArray[j]?.y as number);
                 const endX = inkStrokeXArray[inkStrokeXArray.length - 1] - minX + (lineArray[j].x as number);
                 const endY = inkStrokeYArray[inkStrokeYArray.length - 1] - minY + (lineArray[j].y as number);
-                let closestStartRect:Doc=lineArray[0];
-                let closestStartDistance=9999999;
-                let closestEndRect:Doc=lineArray[0];
-                let closestEndDistance=9999999;
+                let closestStartRect: Doc = lineArray[0];
+                let closestStartDistance = 9999999;
+                let closestEndRect: Doc = lineArray[0];
+                let closestEndDistance = 9999999;
                 rectangleArray.forEach(rectangle => {
-                    const midPoint=this.getMidPoint(rectangle)
-                    if(this.euclideanDistance(midPoint.X,midPoint.Y,startX,startY)<closestStartDistance&&this.euclideanDistance(midPoint.X,midPoint.Y,endX,endY)<closestEndDistance){
-                        if(this.euclideanDistance(midPoint.X,midPoint.Y,startX,startY)<this.euclideanDistance(midPoint.X,midPoint.Y,endX,endY)){
-                            closestStartDistance=this.euclideanDistance(midPoint.X,midPoint.Y,startX,startY);
-                            closestStartRect=rectangle
+                    const midPoint = this.getMidPoint(rectangle);
+                    if (this.euclideanDistance(midPoint.X, midPoint.Y, startX, startY) < closestStartDistance && this.euclideanDistance(midPoint.X, midPoint.Y, endX, endY) < closestEndDistance) {
+                        if (this.euclideanDistance(midPoint.X, midPoint.Y, startX, startY) < this.euclideanDistance(midPoint.X, midPoint.Y, endX, endY)) {
+                            closestStartDistance = this.euclideanDistance(midPoint.X, midPoint.Y, startX, startY);
+                            closestStartRect = rectangle;
+                        } else {
+                            closestEndDistance = this.euclideanDistance(midPoint.X, midPoint.Y, startX, startY);
+                            closestEndRect = rectangle;
                         }
-                        else{
-                            closestEndDistance=this.euclideanDistance(midPoint.X,midPoint.Y,startX,startY);
-                            closestEndRect=rectangle
-                        }
-                    }
-                    else if(this.euclideanDistance(midPoint.X,midPoint.Y,startX,startY)<closestStartDistance){
-                        closestStartDistance=this.euclideanDistance(midPoint.X,midPoint.Y,startX,startY);
-                        closestStartRect=rectangle
+                    } else if (this.euclideanDistance(midPoint.X, midPoint.Y, startX, startY) < closestStartDistance) {
+                        closestStartDistance = this.euclideanDistance(midPoint.X, midPoint.Y, startX, startY);
+                        closestStartRect = rectangle;
+                    } else if (this.euclideanDistance(midPoint.X, midPoint.Y, endX, endY) < closestEndDistance) {
+                        closestEndDistance = this.euclideanDistance(midPoint.X, midPoint.Y, startX, startY);
+                        closestEndRect = rectangle;
                     }
-                    else if(this.euclideanDistance(midPoint.X,midPoint.Y,endX,endY)<closestEndDistance){
-                        closestEndDistance=this.euclideanDistance(midPoint.X,midPoint.Y,startX,startY);
-                        closestEndRect=rectangle
-                    }
-                    
                 });
-                const inkToDelete:Doc=lineArray[j];
-                if(typeof closestStartRect.x==='number'&&typeof closestStartRect.y==='number'&&typeof closestEndRect.x==='number'&&typeof closestEndRect.y==='number'&&typeof closestStartRect.width==='number'&&typeof closestStartRect.height==='number'&&typeof closestEndRect.height==='number'&&typeof closestEndRect.width==='number'){
+                const inkToDelete: Doc = lineArray[j];
+                if (
+                    typeof closestStartRect.x === 'number' &&
+                    typeof closestStartRect.y === 'number' &&
+                    typeof closestEndRect.x === 'number' &&
+                    typeof closestEndRect.y === 'number' &&
+                    typeof closestStartRect.width === 'number' &&
+                    typeof closestStartRect.height === 'number' &&
+                    typeof closestEndRect.height === 'number' &&
+                    typeof closestEndRect.width === 'number'
+                ) {
                     const points: PointData[] = [
                         { X: closestStartRect.x, Y: closestStartRect.y },
                         { X: closestStartRect.x, Y: closestStartRect.y },
                         { X: closestEndRect.x, Y: closestEndRect.y },
-                        { X: closestEndRect.x, Y: closestEndRect.y }
+                        { X: closestEndRect.x, Y: closestEndRect.y },
                     ];
-                    let inkX=0;
-                    let inkY=0;
-                    if(this.getMidPoint(closestEndRect).X<this.getMidPoint(closestStartRect).X){
-                        inkX=this.getMidPoint(closestEndRect).X
-                    }
-                    else{
-                        inkX=this.getMidPoint(closestStartRect).X
+                    let inkX = 0;
+                    let inkY = 0;
+                    if (this.getMidPoint(closestEndRect).X < this.getMidPoint(closestStartRect).X) {
+                        inkX = this.getMidPoint(closestEndRect).X;
+                    } else {
+                        inkX = this.getMidPoint(closestStartRect).X;
                     }
-                    if(this.getMidPoint(closestEndRect).Y<this.getMidPoint(closestStartRect).Y){
-                        inkY=this.getMidPoint(closestEndRect).Y
+                    if (this.getMidPoint(closestEndRect).Y < this.getMidPoint(closestStartRect).Y) {
+                        inkY = this.getMidPoint(closestEndRect).Y;
+                    } else {
+                        inkY = this.getMidPoint(closestStartRect).Y;
                     }
-                    else{
-                        inkY=this.getMidPoint(closestStartRect).Y
-                    }
-                    const newInkDoc:Doc=Docs.Create.InkDocument(
-                        points,
-                        { title: 'stroke',
-                        x: inkX,
-                        y: inkY,
-                        _width: Math.abs(closestEndRect.x+closestEndRect.width/2-closestStartRect.x-closestStartRect.width/2),
-                        _height: Math.abs(closestEndRect.y+closestEndRect.height/2-closestStartRect.y-closestStartRect.height/2),
-                        stroke_showLabel: BoolCast(Doc.UserDoc().activeInkHideTextLabels)}, // prettier-ignore
-                        1)
-                    
-                    DocumentManager.Instance.AddViewRenderedCb(this.Document, (docViewForYourCollection) => {
+                    const newInkDoc = Docs.Create.AudioDocument(''); // get rid of this!!
+                    // const newInkDoc:Doc=Docs.Create.InkDocument(
+                    //     points,
+                    //     { title: 'stroke',
+                    //     x: inkX,
+                    //     y: inkY,
+                    //     strokeWidth: Math.abs(closestEndRect.x+closestEndRect.width/2-closestStartRect.x-closestStartRect.width/2),
+                    //     _height: Math.abs(closestEndRect.y+closestEndRect.height/2-closestStartRect.y-closestStartRect.height/2),
+                    //     stroke_showLabel: BoolCast(Doc.UserDoc().activeInkHideTextLabels)}, // prettier-ignore
+                    //     1)
+
+                    DocumentManager.Instance.AddViewRenderedCb(this.Document, docViewForYourCollection => {
                         if (docViewForYourCollection && docViewForYourCollection.ComponentView) {
-                            if (docViewForYourCollection.ComponentView.addDocument&&docViewForYourCollection.ComponentView.removeDocument) {
-                                 docViewForYourCollection.ComponentView?.removeDocument(inkToDelete)
-                                 docViewForYourCollection.ComponentView?.addDocument(newInkDoc);
-                            
+                            if (docViewForYourCollection.ComponentView.addDocument && docViewForYourCollection.ComponentView.removeDocument) {
+                                docViewForYourCollection.ComponentView?.removeDocument(inkToDelete);
+                                docViewForYourCollection.ComponentView?.addDocument(newInkDoc);
 
-                            
                                 // const bruh2= DocListCast(this.Document.data).filter(doc => doc.title === 'line' || doc.title === 'stroke').map(doc => DocumentManager.Instance.getDocumentView(doc, this.DocumentView?.())).filter(inkView => inkView?.ComponentView instanceof InkingStroke).map(stroke => stroke?.ComponentView);
                                 // console.log(bruh2)
                                 // console.log((bruh2[0] as InkingStroke)?.inkScaledData())
                             }
                         }
-                    });    
-                }           
+                    });
+                }
             }
         }
     }
-    getMidPoint(rectangle:Doc){
-        let midPoint={X:0,Y:0}
-        if(typeof rectangle.x ==='number' && typeof rectangle.width==='number'&&typeof rectangle.y ==='number' && typeof rectangle.height==='number'){
-            midPoint={X:rectangle.x+rectangle.width/2,Y:rectangle.y+rectangle.height/2};
+    getMidPoint(rectangle: Doc) {
+        let midPoint = { X: 0, Y: 0 };
+        if (typeof rectangle.x === 'number' && typeof rectangle.width === 'number' && typeof rectangle.y === 'number' && typeof rectangle.height === 'number') {
+            midPoint = { X: rectangle.x + rectangle.width / 2, Y: rectangle.y + rectangle.height / 2 };
         }
-        return midPoint
+        return midPoint;
     }
     euclideanDistance(x1: number, y1: number, x2: number, y2: number): number {
         const deltaX = x2 - x1;
@@ -486,7 +492,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                         <button className="backButton" type="button" onClick={this.optionButton}>
                             Back
                         </button>
-                        <textarea value={this.inputValue} placeholder="Enter GPT prompt" onChange={this.handleInputChange}onInput={e => this.autoResize(e.target as HTMLTextAreaElement)} />
+                        <textarea value={this.inputValue} placeholder="Enter GPT prompt" onChange={this.handleInputChange} onInput={e => this.autoResize(e.target as HTMLTextAreaElement)} />
                         <div className="rightButtons">
                             <button className="generateButton" type="button" onClick={this.handleRenderClick}>
                                 Generate
@@ -505,14 +511,14 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             </div>
         );
     }
-    handleConvertButton=()=>{
+    handleConvertButton = () => {
         this.Document.menuState = 'mermaidCode';
-        if(typeof this.Document.gptMermaidCode==='string'){
-            this.createInputValue=this.removeFirstEmptyLine(this.Document.gptMermaidCode);
-            console.log(this.Document.gptMermaidCode)
+        if (typeof this.Document.gptMermaidCode === 'string') {
+            this.createInputValue = this.removeFirstEmptyLine(this.Document.gptMermaidCode);
+            console.log(this.Document.gptMermaidCode);
             this.renderMermaidAsync(this.Document.gptMermaidCode);
         }
-    }
+    };
     removeFirstEmptyLine(input: string): string {
         const lines = input.split('\n');
         let emptyLineRemoved = false;
@@ -525,7 +531,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         });
         return resultLines.join('\n');
     }
-    
+
     renderMermaidCode(): React.ReactNode {
         return (
             <div ref={this._dragRef} className="DiagramBox-wrapper">
@@ -557,7 +563,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                             </button>
                         </div>
                     )}
-                    <textarea value={this.createInputValue} placeholder="Enter Mermaid Code" onChange={this.handleInputChangeEditor}/>
+                    <textarea value={this.createInputValue} placeholder="Enter Mermaid Code" onChange={this.handleInputChangeEditor} />
                     <div id={'dashDiv' + this.Document.title} className="diagramBox" />
                 </div>
             </div>
@@ -576,14 +582,14 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         B --> C{Let me think}
         C -->|One| D[Laptop]
         C -->|Two| E[iPhone]
-        C -->|Three| F[fa:fa-car Car]`
+        C -->|Three| F[fa:fa-car Car]`;
         this.renderMermaidAsync(this.createInputValue);
     };
     pieButton = () => {
         this.createInputValue = `pie title Pets adopted by volunteers
         "Dogs" : 386
         "Cats" : 85
-        "Rats" : 15`
+        "Rats" : 15`;
         this.renderMermaidAsync(this.createInputValue);
     };
     timelineButton = () => {
-- 
cgit v1.2.3-70-g09d2


From a21744ddbbc026b64b028b624c3d7c4000706a25 Mon Sep 17 00:00:00 2001
From: eleanor-park <eleanor_park@brown.edu>
Date: Tue, 27 Aug 2024 16:58:22 -0400
Subject: resolved merge conflicts

---
 src/client/views/nodes/DiagramBox.tsx | 136 +---------------------------------
 src/client/views/pdf/PDFViewer.tsx    |   3 -
 2 files changed, 3 insertions(+), 136 deletions(-)

(limited to 'src/client/views/nodes/DiagramBox.tsx')

diff --git a/src/client/views/nodes/DiagramBox.tsx b/src/client/views/nodes/DiagramBox.tsx
index 602bd4990..36deb2d8d 100644
--- a/src/client/views/nodes/DiagramBox.tsx
+++ b/src/client/views/nodes/DiagramBox.tsx
@@ -1,5 +1,3 @@
-/* eslint-disable prettier/prettier */
-/* eslint-disable jsx-a11y/control-has-associated-label */
 import mermaid from 'mermaid';
 import { action, computed, makeObservable, observable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
@@ -19,8 +17,7 @@ import { ViewBoxAnnotatableComponent } from '../DocComponent';
 import { InkingStroke } from '../InkingStroke';
 import './DiagramBox.scss';
 import { FieldView, FieldViewProps } from './FieldView';
-import { PointData } from '../../../pen-gestures/GestureTypes';
-import { InkField } from '../../../fields/InkField';
+import { FormattedTextBox } from './formattedText/FormattedTextBox';
 
 @observer
 export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@@ -53,9 +50,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         mermaid.initialize({
             securityLevel: 'loose',
             startOnLoad: true,
-            darkMode: true,
-            flowchart: { useMaxWidth: false, htmlLabels: true, curve: 'cardinal' },
-            gantt: { useMaxWidth: true, useWidth: 2000 },
+            flowchart: { useMaxWidth: true, htmlLabels: true, curve: 'cardinal' },
         });
         // when a new doc/text/ink/shape is created in the freeform view, this generates the corresponding mermaid diagram code
         reaction(
@@ -178,7 +173,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         return '( )';
     };
 
-    renderGpt(): React.ReactNode {
+    render() {
         return (
             <div className="DIYNodeBox">
                 <div className="DIYNodeBox-searchbar">
@@ -202,131 +197,6 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             </div>
         );
     }
-    exampleButton = () => {
-        if (this.isExampleMenuOpen) {
-            this.isExampleMenuOpen = false;
-        } else {
-            this.isExampleMenuOpen = true;
-        }
-    };
-    flowButton = () => {
-        this.createInputValue = `flowchart TD
-        A[Christmas] -->|Get money| B(Go shopping)
-        B --> C{Let me think}
-        C -->|One| D[Laptop]
-        C -->|Two| E[iPhone]
-        C -->|Three| F[fa:fa-car Car]`;
-        this.renderMermaidAsync(this.createInputValue);
-    };
-    pieButton = () => {
-        this.createInputValue = `pie title Pets adopted by volunteers
-        "Dogs" : 386
-        "Cats" : 85
-        "Rats" : 15`;
-        this.renderMermaidAsync(this.createInputValue);
-    };
-    timelineButton = () => {
-        this.createInputValue = `gantt
-        title A Gantt Diagram
-        dateFormat  YYYY-MM-DD
-        section Section
-        A task           :a1, 2014-01-01, 30d
-        Another task     :after a1  , 20d
-        section Another
-        Task in sec      :2014-01-12  , 12d
-        another task      : 24d`;
-        this.renderMermaidAsync(this.createInputValue);
-    };
-    classButton = () => {
-        this.createInputValue = `classDiagram
-        Animal <|-- Duck
-        Animal <|-- Fish
-        Animal <|-- Zebra
-        Animal : +int age
-        Animal : +String gender
-        Animal: +isMammal()
-        Animal: +mate()
-        class Duck{
-            +String beakColor
-            +swim()
-            +quack()
-        }
-        class Fish{
-            -int sizeInFeet
-            -canEat()
-        }
-        class Zebra{
-            +bool is_wild
-            +run()
-        }`;
-        this.renderMermaidAsync(this.createInputValue);
-    };
-    mindmapButton = () => {
-        this.createInputValue = `mindmap
-        root((mindmap))
-            Origins
-            Long history
-            ::icon(fa fa-book)
-            Popularisation
-                British popular psychology author Tony Buzan
-            Research
-            On effectivness<br/>and features
-            On Automatic creation
-                Uses
-                    Creative techniques
-                    Strategic planning
-                    Argument mapping
-            Tools
-            Pen and paper
-            Mermaid`;
-        this.renderMermaidAsync(this.createInputValue);
-    };
-    handleInputChangeEditor = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
-        if (typeof e.target.value === 'string') {
-            this.createInputValue = e.target.value;
-            this.renderMermaidAsync(e.target.value);
-        }
-    };
-    removeWhitespace(str: string): string {
-        return str.replace(/\s+/g, '');
-    }
-    autoResize(element: HTMLTextAreaElement): void {
-        element.style.height = '5px';
-        element.style.height = element.scrollHeight + 'px';
-    }
-    timeline = `gantt
-    title College Timeline
-    dateFormat  YYYY-MM-DD
-    section Semester 1
-    Orientation           :done,    des1, 2023-08-01, 2023-08-03
-    Classes Start         :active,  des2, 2023-08-04, 2023-12-15
-    Midterm Exams         :         des3, 2023-10-15, 2023-10-20
-    End of Semester       :         des4, 2023-12-16, 2023-12-20
-    section Semester 2
-    Classes Start         :         des5, 2024-01-10, 2024-05-15
-    Spring Break          :         des6, 2024-03-15, 2024-03-22
-    Midterm Exams         :         des7, 2024-03-25, 2024-03-30
-    Final Exams           :         des8, 2024-05-10, 2024-05-15
-    section Summer Break
-    Internship            :         des9, 2024-06-01, 2024-08-31
-    section Semester 3
-    Classes Start         :         des10, 2024-09-01, 2025-12-15
-    Midterm Exams         :         des11, 2024-11-15, 2024-11-20
-    End of Semester       :         des12, 2025-12-16, 2025-12-20
-    section Semester 4
-    Classes Start         :         des13, 2025-01-10, 2025-05-15
-    Spring Break          :         des14, 2025-03-15, 2025-03-22
-    Midterm Exams         :         des15, 2025-03-25, 2025-03-30
-    Final Exams           :         des16, 2025-05-10, 2025-05-15
-    Graduation            :         des17, 2025-05-20, 2025-05-21`;
-    render() {
-        this.switchRenderDiv();
-        return (
-            <div ref={this._ref} className="DiagramBox">
-                {this.renderDiv}
-            </div>
-        );
-    }
 }
 
 Docs.Prototypes.TemplateMap.set(DocumentType.DIAGRAM, {
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 3a2b8884e..5984905d0 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -61,7 +61,6 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
 
     @observable _pageSizes: { width: number; height: number }[] = [];
     @observable _savedAnnotations = new ObservableMap<number, (HTMLDivElement & { marqueeing?: boolean })[]>();
-    @observable _savedTapes = new ObservableMap<number, HTMLDivElement[]>();
     @observable _textSelecting = true;
     @observable _showWaiting = true;
     @observable Index: number = -1;
@@ -580,7 +579,6 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
         return <div className={'pdfViewerDash-text' + (this._props.pointerEvents?.() !== 'none' && this._textSelecting && this._props.isContentActive() ? '-selected' : '')} ref={this._viewer} />;
     }
     savedAnnotations = () => this._savedAnnotations;
-    savedTapes = () => this._savedTapes;
     addDocumentWrapper = (doc: Doc | Doc[]) => this._props.addDocument!(doc);
     render() {
         TraceMobx();
@@ -614,7 +612,6 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
                             docView={this._props.pdfBox.DocumentView!}
                             finishMarquee={this.finishMarquee}
                             savedAnnotations={this.savedAnnotations}
-                            savedTapes={this.savedTapes}
                             selectionText={this.selectionText}
                             annotationLayer={this._annotationLayer.current}
                             marqueeContainer={this._mainCont.current}
-- 
cgit v1.2.3-70-g09d2


From 1585ae672a6e01886fe029de87fe56992d04e0e0 Mon Sep 17 00:00:00 2001
From: Zachary Zhang <zacharyzhang7@gmail.com>
Date: Wed, 4 Sep 2024 23:05:38 -0400
Subject: code changes and comments

---
 eslint.config.mjs                      |  67 +++------------
 package-lock.json                      | 135 ++++++++++++++++-------------
 package.json                           |  10 +--
 src/client/util/Scripting.ts           |   4 +-
 src/client/views/GestureOverlay.tsx    | 152 +++++++++++++++++++--------------
 src/client/views/InkTranscription.tsx  |  78 ++++++++---------
 src/client/views/nodes/DiagramBox.scss |   2 -
 src/client/views/nodes/DiagramBox.tsx  | 145 ++++---------------------------
 8 files changed, 233 insertions(+), 360 deletions(-)

(limited to 'src/client/views/nodes/DiagramBox.tsx')

diff --git a/eslint.config.mjs b/eslint.config.mjs
index 619966f20..8643521de 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -1,57 +1,14 @@
-import pluginJs from '@eslint/js';
-import pluginReactConfig from 'eslint-plugin-react/configs/recommended.js';
-import globals from 'globals';
-import tseslint from 'typescript-eslint';
+import globals from "globals";
+import pluginJs from "@eslint/js";
+import tseslint from "typescript-eslint";
+import pluginReact from "eslint-plugin-react";
 
-export default [
-    {
-        languageOptions: { globals: { ...globals.browser, ...globals.node } },
-    },
-    pluginJs.configs.recommended,
-    ...tseslint.configs.recommended,
-    {
-        rules: {
-            'node/no-missing-import': 0,
-            'no-console': 'off',
-            'func-names': 'off',
-            'no-process-exit': 'off',
-            'object-shorthand': 'off',
-            'class-methods-use-this': 'off',
-            'single-quote': 'off',
-            'max-classes-per-file': 0,
-
-            'react/jsx-filename-extension': [
-                2,
-                {
-                    extensions: ['.js', '.jsx', '.ts', '.tsx'],
-                },
-            ],
 
-            'import/prefer-default-export': 'off',
-            'no-unused-expressions': 'off',
-            '@typescript-eslint/no-unused-expressions': 'off',
-            'prefer-template': 'off',
-            'no-inner-declarations': 'off',
-            'no-plusplus': 'off',
-            'no-multi-assign': 'off',
-            'no-underscore-dangle': 'off',
-            'no-nested-ternary': 'off',
-            'lines-between-class-members': 'off',
-            'no-shadow': 'off',
-            '@typescript-eslint/no-shadow': 'warn',
-            'no-unused-vars': 'off',
-            '@typescript-eslint/no-unused-vars': 'error',
-            '@typescript-eslint/no-namespace': 'off',
-            'react/destructuring-assignment': 0,
-            'prefer-arrow-callback': 'error',
-            'no-return-assign': 'error',
-            'no-await-in-loop': 'error',
-            'no-loop-func': 'error',
-            'no-cond-assign': 'error',
-            'no-use-before-define': 'error',
-            'no-explicit-any': 'error',
-            'no-restricted-globals': ['error', 'event'],
-        },
-    },
-    pluginReactConfig,
-];
+export default [
+  {files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"]},
+  {files: ["**/*.js"], languageOptions: {sourceType: "script"}},
+  {languageOptions: { globals: globals.browser }},
+  pluginJs.configs.recommended,
+  ...tseslint.configs.recommended,
+  pluginReact.configs.flat.recommended,
+];
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index e0cfeaed7..5edcb9a3f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -247,7 +247,7 @@
                 "xregexp": "^5.1.1"
             },
             "devDependencies": {
-                "@eslint/js": "^9.1.1",
+                "@eslint/js": "^9.9.1",
                 "@types/adm-zip": "^0.5.5",
                 "@types/animejs": "^3.1.12",
                 "@types/archiver": "^6.0.2",
@@ -296,9 +296,9 @@
                 "@types/youtube": "^0.1.0",
                 "chai": "^5.0.0",
                 "cross-env": "^7.0.3",
-                "eslint": "^9.9.0",
-                "eslint-plugin-react": "^7.34.1",
-                "globals": "^15.1.0",
+                "eslint": "^9.9.1",
+                "eslint-plugin-react": "^7.35.2",
+                "globals": "^15.9.0",
                 "jsdom": "^25.0.0",
                 "mocha": "^10.2.0",
                 "prettier": "^3.1.0",
@@ -307,7 +307,7 @@
                 "ts-loader": "^9.5.1",
                 "ts-node": "^10.9.1",
                 "ts-node-dev": "^2.0.0",
-                "typescript-eslint": "^8.2.0",
+                "typescript-eslint": "^8.4.0",
                 "webpack-dev-server": "^5.0.4"
             },
             "engines": {
@@ -2679,6 +2679,7 @@
             "version": "9.9.1",
             "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.1.tgz",
             "integrity": "sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==",
+            "license": "MIT",
             "engines": {
                 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
             }
@@ -9994,16 +9995,17 @@
             "dev": true
         },
         "node_modules/@typescript-eslint/eslint-plugin": {
-            "version": "8.3.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.3.0.tgz",
-            "integrity": "sha512-FLAIn63G5KH+adZosDYiutqkOkYEx0nvcwNNfJAf+c7Ae/H35qWwTYvPZUKFj5AS+WfHG/WJJfWnDnyNUlp8UA==",
+            "version": "8.4.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.4.0.tgz",
+            "integrity": "sha512-rg8LGdv7ri3oAlenMACk9e+AR4wUV0yrrG+XKsGKOK0EVgeEDqurkXMPILG2836fW4ibokTB5v4b6Z9+GYQDEw==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "@eslint-community/regexpp": "^4.10.0",
-                "@typescript-eslint/scope-manager": "8.3.0",
-                "@typescript-eslint/type-utils": "8.3.0",
-                "@typescript-eslint/utils": "8.3.0",
-                "@typescript-eslint/visitor-keys": "8.3.0",
+                "@typescript-eslint/scope-manager": "8.4.0",
+                "@typescript-eslint/type-utils": "8.4.0",
+                "@typescript-eslint/utils": "8.4.0",
+                "@typescript-eslint/visitor-keys": "8.4.0",
                 "graphemer": "^1.4.0",
                 "ignore": "^5.3.1",
                 "natural-compare": "^1.4.0",
@@ -10027,15 +10029,16 @@
             }
         },
         "node_modules/@typescript-eslint/parser": {
-            "version": "8.3.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.3.0.tgz",
-            "integrity": "sha512-h53RhVyLu6AtpUzVCYLPhZGL5jzTD9fZL+SYf/+hYOx2bDkyQXztXSc4tbvKYHzfMXExMLiL9CWqJmVz6+78IQ==",
+            "version": "8.4.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.4.0.tgz",
+            "integrity": "sha512-NHgWmKSgJk5K9N16GIhQ4jSobBoJwrmURaLErad0qlLjrpP5bECYg+wxVTGlGZmJbU03jj/dfnb6V9bw+5icsA==",
             "dev": true,
+            "license": "BSD-2-Clause",
             "dependencies": {
-                "@typescript-eslint/scope-manager": "8.3.0",
-                "@typescript-eslint/types": "8.3.0",
-                "@typescript-eslint/typescript-estree": "8.3.0",
-                "@typescript-eslint/visitor-keys": "8.3.0",
+                "@typescript-eslint/scope-manager": "8.4.0",
+                "@typescript-eslint/types": "8.4.0",
+                "@typescript-eslint/typescript-estree": "8.4.0",
+                "@typescript-eslint/visitor-keys": "8.4.0",
                 "debug": "^4.3.4"
             },
             "engines": {
@@ -10055,13 +10058,14 @@
             }
         },
         "node_modules/@typescript-eslint/scope-manager": {
-            "version": "8.3.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.3.0.tgz",
-            "integrity": "sha512-mz2X8WcN2nVu5Hodku+IR8GgCOl4C0G/Z1ruaWN4dgec64kDBabuXyPAr+/RgJtumv8EEkqIzf3X2U5DUKB2eg==",
+            "version": "8.4.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.4.0.tgz",
+            "integrity": "sha512-n2jFxLeY0JmKfUqy3P70rs6vdoPjHK8P/w+zJcV3fk0b0BwRXC/zxRTEnAsgYT7MwdQDt/ZEbtdzdVC+hcpF0A==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "@typescript-eslint/types": "8.3.0",
-                "@typescript-eslint/visitor-keys": "8.3.0"
+                "@typescript-eslint/types": "8.4.0",
+                "@typescript-eslint/visitor-keys": "8.4.0"
             },
             "engines": {
                 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -10072,13 +10076,14 @@
             }
         },
         "node_modules/@typescript-eslint/type-utils": {
-            "version": "8.3.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.3.0.tgz",
-            "integrity": "sha512-wrV6qh//nLbfXZQoj32EXKmwHf4b7L+xXLrP3FZ0GOUU72gSvLjeWUl5J5Ue5IwRxIV1TfF73j/eaBapxx99Lg==",
+            "version": "8.4.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.4.0.tgz",
+            "integrity": "sha512-pu2PAmNrl9KX6TtirVOrbLPLwDmASpZhK/XU7WvoKoCUkdtq9zF7qQ7gna0GBZFN0hci0vHaSusiL2WpsQk37A==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "@typescript-eslint/typescript-estree": "8.3.0",
-                "@typescript-eslint/utils": "8.3.0",
+                "@typescript-eslint/typescript-estree": "8.4.0",
+                "@typescript-eslint/utils": "8.4.0",
                 "debug": "^4.3.4",
                 "ts-api-utils": "^1.3.0"
             },
@@ -10096,10 +10101,11 @@
             }
         },
         "node_modules/@typescript-eslint/types": {
-            "version": "8.3.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.3.0.tgz",
-            "integrity": "sha512-y6sSEeK+facMaAyixM36dQ5NVXTnKWunfD1Ft4xraYqxP0lC0POJmIaL/mw72CUMqjY9qfyVfXafMeaUj0noWw==",
+            "version": "8.4.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.4.0.tgz",
+            "integrity": "sha512-T1RB3KQdskh9t3v/qv7niK6P8yvn7ja1mS7QK7XfRVL6wtZ8/mFs/FHf4fKvTA0rKnqnYxl/uHFNbnEt0phgbw==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
             },
@@ -10109,13 +10115,14 @@
             }
         },
         "node_modules/@typescript-eslint/typescript-estree": {
-            "version": "8.3.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.3.0.tgz",
-            "integrity": "sha512-Mq7FTHl0R36EmWlCJWojIC1qn/ZWo2YiWYc1XVtasJ7FIgjo0MVv9rZWXEE7IK2CGrtwe1dVOxWwqXUdNgfRCA==",
+            "version": "8.4.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.4.0.tgz",
+            "integrity": "sha512-kJ2OIP4dQw5gdI4uXsaxUZHRwWAGpREJ9Zq6D5L0BweyOrWsL6Sz0YcAZGWhvKnH7fm1J5YFE1JrQL0c9dd53A==",
             "dev": true,
+            "license": "BSD-2-Clause",
             "dependencies": {
-                "@typescript-eslint/types": "8.3.0",
-                "@typescript-eslint/visitor-keys": "8.3.0",
+                "@typescript-eslint/types": "8.4.0",
+                "@typescript-eslint/visitor-keys": "8.4.0",
                 "debug": "^4.3.4",
                 "fast-glob": "^3.3.2",
                 "is-glob": "^4.0.3",
@@ -10141,6 +10148,7 @@
             "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
             "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
             "dev": true,
+            "license": "ISC",
             "dependencies": {
                 "brace-expansion": "^2.0.1"
             },
@@ -10156,6 +10164,7 @@
             "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
             "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
             "dev": true,
+            "license": "ISC",
             "bin": {
                 "semver": "bin/semver.js"
             },
@@ -10164,15 +10173,16 @@
             }
         },
         "node_modules/@typescript-eslint/utils": {
-            "version": "8.3.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.3.0.tgz",
-            "integrity": "sha512-F77WwqxIi/qGkIGOGXNBLV7nykwfjLsdauRB/DOFPdv6LTF3BHHkBpq81/b5iMPSF055oO2BiivDJV4ChvNtXA==",
+            "version": "8.4.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.4.0.tgz",
+            "integrity": "sha512-swULW8n1IKLjRAgciCkTCafyTHHfwVQFt8DovmaF69sKbOxTSFMmIZaSHjqO9i/RV0wIblaawhzvtva8Nmm7lQ==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "@eslint-community/eslint-utils": "^4.4.0",
-                "@typescript-eslint/scope-manager": "8.3.0",
-                "@typescript-eslint/types": "8.3.0",
-                "@typescript-eslint/typescript-estree": "8.3.0"
+                "@typescript-eslint/scope-manager": "8.4.0",
+                "@typescript-eslint/types": "8.4.0",
+                "@typescript-eslint/typescript-estree": "8.4.0"
             },
             "engines": {
                 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -10186,12 +10196,13 @@
             }
         },
         "node_modules/@typescript-eslint/visitor-keys": {
-            "version": "8.3.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.3.0.tgz",
-            "integrity": "sha512-RmZwrTbQ9QveF15m/Cl28n0LXD6ea2CjkhH5rQ55ewz3H24w+AMCJHPVYaZ8/0HoG8Z3cLLFFycRXxeO2tz9FA==",
+            "version": "8.4.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.4.0.tgz",
+            "integrity": "sha512-zTQD6WLNTre1hj5wp09nBIDiOc2U5r/qmzo7wxPn4ZgAjHql09EofqhF9WF+fZHzL5aCyaIpPcT2hyxl73kr9A==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "@typescript-eslint/types": "8.3.0",
+                "@typescript-eslint/types": "8.4.0",
                 "eslint-visitor-keys": "^3.4.3"
             },
             "engines": {
@@ -10207,6 +10218,7 @@
             "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
             "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
             "dev": true,
+            "license": "Apache-2.0",
             "engines": {
                 "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
             },
@@ -17452,6 +17464,7 @@
             "version": "9.9.1",
             "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.1.tgz",
             "integrity": "sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==",
+            "license": "MIT",
             "dependencies": {
                 "@eslint-community/eslint-utils": "^4.2.0",
                 "@eslint-community/regexpp": "^4.11.0",
@@ -17507,10 +17520,11 @@
             }
         },
         "node_modules/eslint-plugin-react": {
-            "version": "7.35.0",
-            "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz",
-            "integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==",
+            "version": "7.35.2",
+            "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.2.tgz",
+            "integrity": "sha512-Rbj2R9zwP2GYNcIak4xoAMV57hrBh3hTaR0k7hVjwCQgryE/pw5px4b13EYjduOI0hfXyZhwBxaGpOTbWSGzKQ==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "array-includes": "^3.1.8",
                 "array.prototype.findlast": "^1.2.5",
@@ -18102,6 +18116,7 @@
             "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
             "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "@nodelib/fs.stat": "^2.0.2",
                 "@nodelib/fs.walk": "^1.2.3",
@@ -18118,6 +18133,7 @@
             "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
             "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
             "dev": true,
+            "license": "ISC",
             "dependencies": {
                 "is-glob": "^4.0.1"
             },
@@ -19306,6 +19322,7 @@
             "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz",
             "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">=18"
             },
@@ -19459,7 +19476,8 @@
             "version": "1.4.0",
             "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
             "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
-            "dev": true
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/grid-index": {
             "version": "1.1.0",
@@ -27568,6 +27586,7 @@
             "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
             "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">= 8"
             }
@@ -37391,6 +37410,7 @@
             "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz",
             "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">=16"
             },
@@ -38089,14 +38109,15 @@
             "integrity": "sha512-7sI4e/bZijOzyURng88oOFZCISQPTHozfE2sUu5AviFYk5QV7fYGb6YiDl+vKjF/pICA354JImBImL9XJWUvdQ=="
         },
         "node_modules/typescript-eslint": {
-            "version": "8.3.0",
-            "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.3.0.tgz",
-            "integrity": "sha512-EvWjwWLwwKDIJuBjk2I6UkV8KEQcwZ0VM10nR1rIunRDIP67QJTZAHBXTX0HW/oI1H10YESF8yWie8fRQxjvFA==",
+            "version": "8.4.0",
+            "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.4.0.tgz",
+            "integrity": "sha512-67qoc3zQZe3CAkO0ua17+7aCLI0dU+sSQd1eKPGq06QE4rfQjstVXR6woHO5qQvGUa550NfGckT4tzh3b3c8Pw==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "@typescript-eslint/eslint-plugin": "8.3.0",
-                "@typescript-eslint/parser": "8.3.0",
-                "@typescript-eslint/utils": "8.3.0"
+                "@typescript-eslint/eslint-plugin": "8.4.0",
+                "@typescript-eslint/parser": "8.4.0",
+                "@typescript-eslint/utils": "8.4.0"
             },
             "engines": {
                 "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
diff --git a/package.json b/package.json
index cfe10d02f..5b3f3edc1 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,7 @@
         "tsc": "tsc -t es5"
     },
     "devDependencies": {
-        "@eslint/js": "^9.1.1",
+        "@eslint/js": "^9.9.1",
         "@types/adm-zip": "^0.5.5",
         "@types/animejs": "^3.1.12",
         "@types/archiver": "^6.0.2",
@@ -72,9 +72,9 @@
         "@types/youtube": "^0.1.0",
         "chai": "^5.0.0",
         "cross-env": "^7.0.3",
-        "eslint": "^9.9.0",
-        "eslint-plugin-react": "^7.34.1",
-        "globals": "^15.1.0",
+        "eslint": "^9.9.1",
+        "eslint-plugin-react": "^7.35.2",
+        "globals": "^15.9.0",
         "jsdom": "^25.0.0",
         "mocha": "^10.2.0",
         "prettier": "^3.1.0",
@@ -83,7 +83,7 @@
         "ts-loader": "^9.5.1",
         "ts-node": "^10.9.1",
         "ts-node-dev": "^2.0.0",
-        "typescript-eslint": "^8.2.0",
+        "typescript-eslint": "^8.4.0",
         "webpack-dev-server": "^5.0.4"
     },
     "dependencies": {
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index c63d3d7cb..68dab8f99 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -1,7 +1,7 @@
 // export const ts = (window as any).ts;
 // import * as typescriptlib from '!!raw-loader!../../../node_modules/typescript/lib/lib.d.ts'
 // import * as typescriptes5 from '!!raw-loader!../../../node_modules/typescript/lib/lib.es5.d.ts'
-import typescriptlib from 'type_decls.d';
+//import typescriptlib from 'type_decls.d';
 import * as ts from 'typescript';
 import { Doc, FieldType } from '../../fields/Doc';
 import { RefField } from '../../fields/RefField';
@@ -248,7 +248,7 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp
     const funcScript = `(function(${paramString})${reqTypes} { ${body} })`;
     host.writeFile('file.ts', funcScript);
 
-    if (typecheck) host.writeFile('node_modules/typescript/lib/lib.d.ts', typescriptlib);
+    //if (typecheck) host.writeFile('node_modules/typescript/lib/lib.d.ts', typescriptlib);
     const program = ts.createProgram(['file.ts'], {}, host);
     const testResult = program.emit();
     const outputText = host.readFile('file.js');
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index 0c797adf2..c1ac3ab06 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -33,8 +33,6 @@ import { returnEmptyDocViewList } from './StyleProvider';
 import { ActiveFillColor, DocumentView } from './nodes/DocumentView';
 import { CollectionFreeFormView } from './collections/collectionFreeForm';
 import { InkingStroke } from './InkingStroke';
-import { NullLiteral } from 'typescript';
-import { isNull } from 'lodash';
 export enum ToolglassTools {
     InkToText = 'inktotext',
     IgnoreGesture = 'ignoregesture',
@@ -45,10 +43,12 @@ interface GestureOverlayProps {
     isActive: boolean;
 }
 @observer
+/**
+ * class for gestures. will determine if what the user drew is a gesture, and will transform the ink stroke into the shape the user
+ * drew or perform the gesture's action
+ */
 export class GestureOverlay extends ObservableReactComponent<React.PropsWithChildren<GestureOverlayProps>> {
-    // eslint-disable-next-line no-use-before-define
     static Instance: GestureOverlay;
-    // eslint-disable-next-line no-use-before-define
     static Instances: GestureOverlay[] = [];
 
     @observable public InkShape: Opt<Gestures> = undefined;
@@ -131,20 +131,24 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
             // SetActiveArrowEnd('none');
         }
     }
-    isScribble(inkPoints: any) {
+    /**
+     * this method returns if what the user drew is a scribble. if it is, it will determine what documents need
+     * to be deleted and then it will delete them.
+     * @returns
+     */
+    isScribble() {
         const ffView = DocumentView.allViews().find(view => view.ComponentView instanceof CollectionFreeFormView);
-        const points = this._points.map(p => ({ X: p.X, Y: p.Y }));
-        const cuspArray = this.getNumberOfCusps(points);
-        let cuspBooleanArray: boolean[] = [];
-        let docsToDelete: Doc[] = [];
+        const cuspArray = this.getCusps();
+        const cuspBooleanArray: boolean[] = [];
+        const docsToDelete: Doc[] = [];
         const childDocs = (ffView?.ComponentView as CollectionFreeFormView).childDocs;
         childDocs.filter(doc => doc.type === 'ink').map(doc => DocumentView.getDocumentView(doc, DocumentView.getDocumentView(doc)));
         if ((ffView?.ComponentView as CollectionFreeFormView).childDocs) {
+            //how many cusps the scribble hsa
             if (cuspArray.length > 4) {
-                console.log('there are enough cusps');
                 for (let i = 0; i < cuspArray.length - 2; i++) {
                     let hasDocInTriangle = false;
-                    for (let doc of childDocs) {
+                    for (const doc of childDocs) {
                         const point1 = cuspArray[i];
                         const point2 = cuspArray[i + 1];
                         const point3 = cuspArray[i + 2];
@@ -152,9 +156,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
                         const otherInk = DocumentView.getDocumentView(doc)?.ComponentView as InkingStroke;
                         const { inkData: otherInkData } = otherInk?.inkScaledData() ?? { inkData: [] };
                         const otherScreenPts = otherInkData.map(point => otherInk.ptToScreen(point));
-                        console.log(otherScreenPts);
-                        console.log((DocumentView.getDocumentView(doc)?.ComponentView as InkingStroke).inkScaledData().inkData.map(point => ({ X: point.X, Y: point.Y })));
-                        console.log(triangleObject);
                         if (doc.title === 'line') {
                             if (this.doesLineIntersectTriangle(otherScreenPts, triangleObject)) {
                                 docsToDelete.push(doc);
@@ -182,6 +183,12 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
         }
         return false;
     }
+    /**
+     * this method determines if what the user drew is a scribble based on certain criteria.
+     * @param cuspBooleanArray will take in an array of booleans tht represent what triangles in the scribble
+     * has an object in it. the 1st triangle is the 0th index, 2nd triangle is the 1st index and so on.
+     * @returns
+     */
     determineIfScribble(cuspBooleanArray: boolean[]) {
         if (!cuspBooleanArray) {
             return false;
@@ -193,21 +200,29 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
                 hasObjectInFirstAndLast25 = false;
             }
         }
-        console.log(cuspBooleanArray);
-        console.log(hasObjectInFirstAndLast25);
         const trueCount = cuspBooleanArray.filter(value => value).length;
         const percentageTrues = trueCount / cuspBooleanArray.length;
-        if (percentageTrues > 0.65 || hasObjectInFirstAndLast25) {
-            console.log('requirements are met');
-        }
         return percentageTrues > 0.65 || hasObjectInFirstAndLast25;
     }
+    /**
+     * determines if two rectangles are overlapping each other
+     * @param rect1 the rectangle object has has a minX,maxX,minY, and maxY
+     * @param rect2
+     * @returns
+     */
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
     isRectangleOverlap(rect1: any, rect2: any): boolean {
         const noOverlap = rect1.maxX < rect2.minX || rect1.minX > rect2.maxX || rect1.maxY < rect2.minY || rect1.minY > rect2.maxY;
 
         return !noOverlap;
     }
-    isPointInTriangle(pt: { X: number; Y: number }, triangle: any): boolean {
+    /**
+     * determines if there is a point in a triangle used to determine what triangles in the scribble have an object
+     * @param pt the point in question
+     * @param triangle the triangle with 3 points
+     * @returns true or false if point is in triangle
+     */
+    isPointInTriangle(pt: { X: number; Y: number }, triangle: { p1: { X: number; Y: number }; p2: { X: number; Y: number }; p3: { X: number; Y: number } }): boolean {
         const area = (v1: { X: number; Y: number }, v2: { X: number; Y: number }, v3: { X: number; Y: number }) => Math.abs((v1.X * (v2.Y - v3.Y) + v2.X * (v3.Y - v1.Y) + v3.X * (v1.Y - v2.Y)) / 2.0);
 
         const A = area(triangle.p1, triangle.p2, triangle.p3);
@@ -218,16 +233,29 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
 
         return A === A1 + A2 + A3;
     }
+    /**
+     * determines if any points in an array are in a triangle
+     * @param triangle the triangle with 3 points
+     * @param points the point in question
+     * @returns true or false if point is in triangle
+     */
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
     isAnyPointInTriangle(triangle: any, points: any[]): boolean {
         for (const point of points) {
-            //console.log(point.X + '     ' + point.Y);
-            //console.log(triangle);
             if (this.isPointInTriangle(point, triangle)) {
                 return true;
             }
         }
         return false;
     }
+    /**
+     * determines if a line intersects a triangle. used for scribble gesture since the line doesnt have a lot
+     * of points across is so isPointInTriangle will not work for it.
+     * @param line is pointData
+     * @param triangle triangle with 3 points
+     * @returns true or false if it intersects
+     */
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
     doesLineIntersectTriangle(line: any, triangle: any): boolean {
         const edges = [
             { start: triangle.p1, end: triangle.p2 },
@@ -243,6 +271,14 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
 
         return false;
     }
+    /**
+     * used in doesLineIntersectTriangle, splits up the triangle into 3 lines and runs this method
+     * individually
+     * @param line1 point data where 0th index is the coordinate of beginnning of line and last index is the coordinate of end of limne
+     * @param line2 same thing
+     * @returns
+     */
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
     doLinesIntersect(line1: any, line2: any): boolean {
         const A = line1[0];
         const B = line1[line1.length - 1];
@@ -260,7 +296,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
     }
     @action
     onPointerUp = () => {
-        console.log('pointer up');
         DocumentView.DownDocView = undefined;
         if (this._points.length > 1) {
             const B = this.svgBounds;
@@ -277,7 +312,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
                 // need to decide when to turn gestures back on
                 const result = points.length > 2 && GestureUtils.GestureRecognizer.Recognize([points]);
                 let actionPerformed = false;
-                //console.log(result);
                 if (Doc.UserDoc().recognizeGestures && result && result.Score > 0.7) {
                     switch (result.Name) {
                         case Gestures.Line:
@@ -286,21 +320,17 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
                         case Gestures.Circle:
                             this.makeBezierPolygon(result.Name, true);
                             actionPerformed = this.dispatchGesture(result.Name);
-                            console.log(result.Name);
-                            console.log();
                             break;
                         case Gestures.Scribble:
-                            console.log('scribble');
                             break;
                         case Gestures.RightAngle:
                             this.convertToText();
                             this._points = [];
-                            console.log('RightAngle');
                             return;
                         default:
                     }
                 }
-                if (this.isScribble(points)) {
+                if (this.isScribble()) {
                     this._points = [];
                     return;
                 }
@@ -323,7 +353,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
                     const dist = Math.sqrt(
                         (controlPoints[0].X - controlPoints.lastElement().X) * (controlPoints[0].X - controlPoints.lastElement().X) + (controlPoints[0].Y - controlPoints.lastElement().Y) * (controlPoints[0].Y - controlPoints.lastElement().Y)
                     );
-                    // eslint-disable-next-line prefer-destructuring
                     if (controlPoints.length > 4 && dist < 10) controlPoints[controlPoints.length - 1] = controlPoints[0];
                     this._points.length = 0;
                     this._points.push(...controlPoints);
@@ -333,9 +362,12 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
         }
         this._points.length = 0;
     };
+    /**
+     * used in the rightAngle gesture to convert handwriting into text. will only work on collections
+     * TODO: make it work on individual ink docs.
+     */
     convertToText() {
         const ffView = DocumentView.allViews().find(view => view.ComponentView instanceof CollectionFreeFormView);
-        let docsToBeConverted: Doc[] = [];
         let minX = 999999999;
         let maxX = -999999999;
         let minY = 999999999;
@@ -345,15 +377,9 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
             .forEach(doc => {
                 if (typeof doc.width === 'number' && typeof doc.height === 'number' && typeof doc.x === 'number' && typeof doc.y === 'number') {
                     const bounds = DocumentView.getDocumentView(doc)?.getBounds;
-                    console.log(DocumentView.getDocumentView(doc));
-                    console.log(bounds);
                     if (bounds) {
                         const rect1 = { minX: bounds.left, maxX: bounds.right, minY: bounds.top, maxY: bounds.bottom };
-                        console.log(rect1);
-                        console.log(this.getExtremeCoordinates(this._points));
-                        const points = this._points.map(p => ({ X: p.X, Y: p.Y }));
-                        console.log(points);
-                        if (this.isRectangleOverlap(rect1, this.getExtremeCoordinates(this._points))) {
+                        if (this.isRectangleOverlap(rect1, this.getExtremeCoordinates())) {
                             if (doc.x < minX) {
                                 minX = doc.x;
                             }
@@ -373,35 +399,23 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
                                 ffView.ComponentView.addDocument(newDoc);
                                 ffView.ComponentView.removeDocument(doc);
                             }
-                            //docsToBeConverted.push(doc);
                         }
                     }
                 }
             });
-        // const collectionDoc = Docs.Create.FreeformDocument(docsToBeConverted, { title: '', x: minX as number, y: maxY as number });
-        // collectionDoc.height = 50;
-        // collectionDoc.width = 50;
-        // if (ffView?.ComponentView?.addDocument) {
-        //     ffView.ComponentView.addDocument(collectionDoc);
-        // }
-        // DocumentView.getDocumentView(collectionDoc)?.ComponentView?.updateIcon;
-        // const newDoc = Docs.Create.TextDocument(doc.transcription as string, { title: '', x: doc.x as number, y: maxY });
-        // newDoc.height = 50;
-        // if (ffView?.ComponentView?.addDocument) {
-        //     ffView.ComponentView.addDocument(newDoc);
-        // }
     }
-    getNumberOfCusps(points: any) {
-        let arrayOfPoints: any[] = [];
+    /**
+     * used to determine how many cusps and where the cusps are in order
+     * @returns will return an array containing the coordinates of the sharp cusps
+     */
+    getCusps() {
+        const points = this._points.map(p => ({ X: p.X, Y: p.Y }));
+        const arrayOfPoints: { X: number; Y: number }[] = [];
         arrayOfPoints.push(points[0]);
         for (let i = 0; i < points.length - 2; i++) {
             const point1 = points[i];
             const point2 = points[i + 1];
             const point3 = points[i + 2];
-            // console.log(point1);
-            // console.log(point2);
-            // console.log(point3);
-            // console.log(this.find_angle(point1, point2, point3));
             if (this.find_angle(point1, point2, point3) < 90) {
                 arrayOfPoints.push(point2);
             }
@@ -409,7 +423,12 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
         arrayOfPoints.push(points[points.length - 1]);
         return arrayOfPoints;
     }
-    getExtremeCoordinates(coordinates: any[]) {
+    /**
+     * will look through an array of point data and return the coordinates of the smallest box that can fit all the points
+     * @returns the minX,maxX,minY,maxY of the box
+     */
+    getExtremeCoordinates() {
+        const coordinates = this._points;
         if (coordinates.length === 0) {
             throw new Error('Coordinates array is empty');
         }
@@ -432,10 +451,15 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
             maxY,
         };
     }
-    find_angle(A: any, B: any, C: any) {
-        let AB = Math.sqrt(Math.pow(B.X - A.X, 2) + Math.pow(B.Y - A.Y, 2));
-        let BC = Math.sqrt(Math.pow(B.X - C.X, 2) + Math.pow(B.Y - C.Y, 2));
-        let AC = Math.sqrt(Math.pow(C.X - A.X, 2) + Math.pow(C.Y - A.Y, 2));
+    /**
+     * takes in three points and then determines the angle of the points. used to determine if the cusp
+     * is sharp enoug
+     * @returns
+     */
+    find_angle(A: { X: number; Y: number }, B: { X: number; Y: number }, C: { X: number; Y: number }) {
+        const AB = Math.sqrt(Math.pow(B.X - A.X, 2) + Math.pow(B.Y - A.Y, 2));
+        const BC = Math.sqrt(Math.pow(B.X - C.X, 2) + Math.pow(B.Y - C.Y, 2));
+        const AC = Math.sqrt(Math.pow(C.X - A.X, 2) + Math.pow(C.Y - A.Y, 2));
         return Math.acos((BC * BC + AB * AB - AC * AC) / (2 * BC * AB)) * (180 / Math.PI);
     }
     makeBezierPolygon = (shape: string, gesture: boolean) => {
@@ -636,7 +660,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
                 this._strokes.map((l, i) => {
                     const b = { left: -20000, right: 20000, top: -20000, bottom: 20000, width: 40000, height: 40000 }; // this.getBounds(l, true);
                     return (
-                        // eslint-disable-next-line react/no-array-index-key
                         <svg key={i} width={b.width} height={b.height} style={{ top: 0, left: 0, transform: `translate(${b.left}px, ${b.top}px)`, pointerEvents: 'none', position: 'absolute', zIndex: 30000, overflow: 'visible' }}>
                             {InteractionUtils.CreatePolyline(
                                 l,
@@ -758,7 +781,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
 }
 
 ScriptingGlobals.add('GestureOverlay', GestureOverlay);
-// eslint-disable-next-line prefer-arrow-callback
 ScriptingGlobals.add(function setPen(width: string, color: string, fill: string, arrowStart: string, arrowEnd: string, dash: string) {
     runInAction(() => {
         GestureOverlay.Instance.SavedColor = ActiveInkColor();
@@ -771,7 +793,6 @@ ScriptingGlobals.add(function setPen(width: string, color: string, fill: string,
         SetActiveDash(dash);
     });
 });
-// eslint-disable-next-line prefer-arrow-callback
 ScriptingGlobals.add(function resetPen() {
     runInAction(() => {
         SetActiveInkColor(GestureOverlay.Instance.SavedColor ?? 'rgb(0, 0, 0)');
@@ -779,7 +800,6 @@ ScriptingGlobals.add(function resetPen() {
     });
 }, 'resets the pen tool');
 ScriptingGlobals.add(
-    // eslint-disable-next-line prefer-arrow-callback
     function createText(text: string, X: number, Y: number) {
         GestureOverlay.Instance.dispatchGesture(Gestures.Text, [{ X, Y }], text);
     },
diff --git a/src/client/views/InkTranscription.tsx b/src/client/views/InkTranscription.tsx
index 93f054462..d2589b139 100644
--- a/src/client/views/InkTranscription.tsx
+++ b/src/client/views/InkTranscription.tsx
@@ -3,7 +3,7 @@ import { action, observable } from 'mobx';
 import * as React from 'react';
 import { Doc, DocListCast } from '../../fields/Doc';
 import { InkData, InkField, InkTool } from '../../fields/InkField';
-import { Cast, DateCast, ImageCast, NumCast, StrCast } from '../../fields/Types';
+import { Cast, DateCast, ImageCast, NumCast } from '../../fields/Types';
 import { aggregateBounds } from '../../Utils';
 import { DocumentType } from '../documents/DocumentTypes';
 import { CollectionFreeFormView } from './collections/collectionFreeForm';
@@ -11,11 +11,8 @@ import { InkingStroke } from './InkingStroke';
 import './InkTranscription.scss';
 import { Docs } from '../documents/Documents';
 import { DocumentView } from './nodes/DocumentView';
-import { Number } from 'mongoose';
-import { NumberArray } from 'd3';
 import { ImageField } from '../../fields/URLField';
 import { gptHandwriting } from '../apis/gpt/GPT';
-import * as fs from 'fs';
 import { URLField } from '../../fields/URLField';
 /**
  * Class component that handles inking in writing mode
@@ -23,16 +20,22 @@ import { URLField } from '../../fields/URLField';
 export class InkTranscription extends React.Component {
     static Instance: InkTranscription;
 
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
     @observable _mathRegister: any = undefined;
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
     @observable _mathRef: any = undefined;
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
     @observable _textRegister: any = undefined;
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
     @observable _textRef: any = undefined;
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
     @observable iinkEditor: any = undefined;
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
     private lastJiix: any;
     private currGroup?: Doc;
     private collectionFreeForm?: CollectionFreeFormView;
 
-    constructor(props: Readonly<{}>) {
+    constructor(props: Readonly<object>) {
         super(props);
 
         InkTranscription.Instance = this;
@@ -44,9 +47,9 @@ export class InkTranscription extends React.Component {
     }
 
     @action
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
     setMathRef = async (r: any) => {
         if (!this._textRegister && r) {
-            let editor;
             const options = {
                 configuration: {
                     server: {
@@ -61,21 +64,22 @@ export class InkTranscription extends React.Component {
                     },
                 },
             };
-
-            editor = new iink.Editor(r, options as any);
+            // eslint-disable-next-line @typescript-eslint/no-explicit-any
+            const editor = new iink.Editor(r, options as any);
 
             await editor.initialize();
 
             this._textRegister = r;
+            // eslint-disable-next-line @typescript-eslint/no-explicit-any
             r?.addEventListener('exported', (e: any) => this.exportInk(e, this._textRef));
 
             return (this._textRef = r);
         }
     };
     @action
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
     setTextRef = async (r: any) => {
         if (!this._textRegister && r) {
-            let editor;
             const options = {
                 configuration: {
                     server: {
@@ -90,12 +94,13 @@ export class InkTranscription extends React.Component {
                     },
                 },
             };
-
-            editor = new iink.Editor(r, options as any);
+            // eslint-disable-next-line @typescript-eslint/no-explicit-any
+            const editor = new iink.Editor(r, options as any);
 
             await editor.initialize();
             this.iinkEditor = editor;
             this._textRegister = r;
+            // eslint-disable-next-line @typescript-eslint/no-explicit-any
             r?.addEventListener('exported', (e: any) => this.exportInk(e, this._textRef));
 
             return (this._textRef = r);
@@ -124,28 +129,9 @@ export class InkTranscription extends React.Component {
                 strokes.push(d.inkData.map(pd => inkStroke.ptToScreen({ X: pd.X, Y: pd.Y })));
                 times.push(DateCast(i.author_date).getDate().getTime());
             });
-        console.log(strokes);
-        console.log(
-            `this.Multistrokes.push(
-            new Multistroke(
-                Gestures.Scribble,
-                useBoundedRotationInvariance,
-                new Array([
-                    ` +
-                this.convertPointsToString(strokes) +
-                `
-                ])
-            )
-        )
-        `
-        );
-        //console.log(this.convertPointsToString(strokes));
-        //console.log(this.convertPointsToString2(strokes));
         this.currGroup = groupDoc;
         const pointerData = strokes.map((stroke, i) => this.inkJSON(stroke, times[i]));
-        const processGestures = false;
         if (math) {
-            console.log('math');
             this.iinkEditor.importPointEvents(pointerData);
         } else {
             this.iinkEditor.importPointEvents(pointerData);
@@ -172,9 +158,9 @@ export class InkTranscription extends React.Component {
             t: number;
             p: number;
         }
-        let strokeObjects: strokeData[] = [];
+        const strokeObjects: strokeData[] = [];
         stroke.forEach(point => {
-            let tempObject: strokeData = {
+            const tempObject: strokeData = {
                 x: point.X,
                 y: point.Y,
                 t: time,
@@ -220,6 +206,7 @@ export class InkTranscription extends React.Component {
      * @param e the event objects
      * @param ref the ref to the editor
      */
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
     exportInk = async (e: any, ref: any) => {
         const exports = e.detail['application/vnd.myscript.jiix'];
         if (exports) {
@@ -236,6 +223,7 @@ export class InkTranscription extends React.Component {
                     this.lastJiix = JSON.parse(exports['application/vnd.myscript.jiix']);
                     // map timestamp to strokes
                     const timestampWord = new Map<number, string>();
+                    // eslint-disable-next-line @typescript-eslint/no-explicit-any
                     this.lastJiix.words.map((word: any) => {
                         if (word.items) {
                             word.items.forEach((i: { id: string; timestamp: string; X: Array<number>; Y: Array<number>; F: Array<number> }) => {
@@ -271,10 +259,7 @@ export class InkTranscription extends React.Component {
 
                 if (this.currGroup && text) {
                     DocumentView.getDocumentView(this.currGroup)?.ComponentView?.updateIcon?.();
-                    let image = await this.getIcon();
-                    const pathname = image?.url.href as string;
-                    console.log(image?.url);
-                    console.log(image);
+                    const image = await this.getIcon();
                     const { href } = (image as URLField).url;
                     const hrefParts = href.split('.');
                     const hrefComplete = `${hrefParts[0]}_o.${hrefParts[1]}`;
@@ -282,9 +267,8 @@ export class InkTranscription extends React.Component {
                     try {
                         const hrefBase64 = await this.imageUrlToBase64(hrefComplete);
                         response = await gptHandwriting(hrefBase64);
-                        console.log(response);
-                    } catch (error) {
-                        console.log('bad things have happened');
+                    } catch {
+                        console.error('Error getting image');
                     }
                     const textBoxText = 'iink: ' + text + '\n' + '\n' + 'ChatGPT: ' + response;
                     this.currGroup.transcription = response;
@@ -300,16 +284,22 @@ export class InkTranscription extends React.Component {
             }
         }
     };
+    /**
+     * gets the icon of the collection that was just made
+     * @returns the image of the collection
+     */
     async getIcon() {
         const docView = DocumentView.getDocumentView(this.currGroup);
-        console.log(this.currGroup);
         if (docView) {
-            console.log(docView);
             docView.ComponentView?.updateIcon?.();
             return new Promise<ImageField | undefined>(res => setTimeout(() => res(ImageCast(docView.Document.icon)), 1000));
         }
         return undefined;
     }
+    /**
+     * converts the image to base url formate
+     * @param imageUrl imageurl taken from the collection icon
+     */
     imageUrlToBase64 = async (imageUrl: string): Promise<string> => {
         try {
             const response = await fetch(imageUrl);
@@ -413,8 +403,8 @@ export class InkTranscription extends React.Component {
         }
 
         // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs
-        newCollection && docView.props.addDocument?.(newCollection);
         if (newCollection) {
+            docView.props.addDocument?.(newCollection);
             newCollection.hasTextBox = false;
         }
         return newCollection;
@@ -423,8 +413,8 @@ export class InkTranscription extends React.Component {
     render() {
         return (
             <div className="ink-transcription">
-                <div className="math-editor" ref={this.setMathRef} touch-action="none"></div>
-                <div className="text-editor" ref={this.setTextRef} touch-action="none"></div>
+                <div className="math-editor" ref={this.setMathRef}></div>
+                <div className="text-editor" ref={this.setTextRef}></div>
             </div>
         );
     }
diff --git a/src/client/views/nodes/DiagramBox.scss b/src/client/views/nodes/DiagramBox.scss
index b43f961d0..8a7863c14 100644
--- a/src/client/views/nodes/DiagramBox.scss
+++ b/src/client/views/nodes/DiagramBox.scss
@@ -21,7 +21,6 @@
         justify-content: center;
         align-items: center;
         width: 100%;
-        height: $searchbarHeight;
         padding: 10px;
 
         input[type='text'] {
@@ -40,7 +39,6 @@
         justify-content: center;
         align-items: center;
         width: 100%;
-        height: calc(100% - $searchbarHeight);
         .diagramBox {
             flex: 1;
             display: flex;
diff --git a/src/client/views/nodes/DiagramBox.tsx b/src/client/views/nodes/DiagramBox.tsx
index 79cf39152..0d755fdbe 100644
--- a/src/client/views/nodes/DiagramBox.tsx
+++ b/src/client/views/nodes/DiagramBox.tsx
@@ -1,5 +1,3 @@
-/* eslint-disable prettier/prettier */
-/* eslint-disable jsx-a11y/control-has-associated-label */
 import mermaid from 'mermaid';
 import { action, computed, makeObservable, observable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
@@ -20,7 +18,9 @@ import { InkingStroke } from '../InkingStroke';
 import './DiagramBox.scss';
 import { FieldView, FieldViewProps } from './FieldView';
 import { FormattedTextBox } from './formattedText/FormattedTextBox';
-
+/**
+ * this is a class for the diagram box doc type that can be found in the tools section of the side bar
+ */
 @observer
 export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     public static LayoutString(fieldKey: string) {
@@ -37,23 +37,12 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         super(props);
         makeObservable(this);
     }
-    @observable renderDiv: React.ReactNode;
-    @observable inputValue = '';
-    @observable createInputValue = '';
-    @observable loading = false;
-    @observable errorMessage = '';
-    @observable mermaidCode = '';
-    @observable isExampleMenuOpen = false;
+
     @observable _showCode = false;
     @observable _inputValue = '';
     @observable _generating = false;
     @observable _errorMessage = '';
 
-    @action handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
-        this.inputValue = e.target.value;
-        console.log(e.target.value);
-    };
-
     @computed get mermaidcode() {
         return Cast(this.Document[DocData].text, RichTextField, null)?.Text ?? '';
     }
@@ -74,14 +63,21 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             { fireImmediately: true }
         );
     }
+    /**
+     * helper method for renderMermaidAsync
+     * @param str string containing the mermaid code
+     * @returns
+     */
     renderMermaid = (str: string) => {
         try {
             return mermaid.render('graph' + Date.now(), str);
-        } catch (error) {
+        } catch {
             return { svg: '', bindFunctions: undefined };
         }
     };
-
+    /**
+     * will update the div containing the mermaid diagram to render the new mermaidCode
+     */
     renderMermaidAsync = async (mermaidCode: string, dashDiv: HTMLDivElement) => {
         try {
             const { svg, bindFunctions } = await this.renderMermaid(mermaidCode);
@@ -112,7 +108,9 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             res
         );
     }, 'set mermaid code');
-
+    /**
+     * will generate mermaid code with GPT based on what the user requested
+     */
     generateMermaidCode = action(() => {
         this._generating = true;
         const prompt = 'Write this in mermaid code and only give me the mermaid code: ' + this._inputValue;
@@ -212,117 +210,6 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             </div>
         );
     }
-    exampleButton = () => {
-        if (this.isExampleMenuOpen) {
-            this.isExampleMenuOpen = false;
-        } else {
-            this.isExampleMenuOpen = true;
-        }
-    };
-    flowButton = () => {
-        this.createInputValue = `flowchart TD
-        A[Christmas] -->|Get money| B(Go shopping)
-        B --> C{Let me think}
-        C -->|One| D[Laptop]
-        C -->|Two| E[iPhone]
-        C -->|Three| F[fa:fa-car Car]`;
-    };
-    pieButton = () => {
-        this.createInputValue = `pie title Pets adopted by volunteers
-        "Dogs" : 386
-        "Cats" : 85
-        "Rats" : 15`;
-    };
-    timelineButton = () => {
-        this.createInputValue = `gantt
-        title A Gantt Diagram
-        dateFormat  YYYY-MM-DD
-        section Section
-        A task           :a1, 2014-01-01, 30d
-        Another task     :after a1  , 20d
-        section Another
-        Task in sec      :2014-01-12  , 12d
-        another task      : 24d`;
-    };
-    classButton = () => {
-        this.createInputValue = `classDiagram
-        Animal <|-- Duck
-        Animal <|-- Fish
-        Animal <|-- Zebra
-        Animal : +int age
-        Animal : +String gender
-        Animal: +isMammal()
-        Animal: +mate()
-        class Duck{
-            +String beakColor
-            +swim()
-            +quack()
-        }
-        class Fish{
-            -int sizeInFeet
-            -canEat()
-        }
-        class Zebra{
-            +bool is_wild
-            +run()
-        }`;
-    };
-    mindmapButton = () => {
-        this.createInputValue = `mindmap
-        root((mindmap))
-            Origins
-            Long history
-            ::icon(fa fa-book)
-            Popularisation
-                British popular psychology author Tony Buzan
-            Research
-            On effectivness<br/>and features
-            On Automatic creation
-                Uses
-                    Creative techniques
-                    Strategic planning
-                    Argument mapping
-            Tools
-            Pen and paper
-            Mermaid`;
-    };
-    handleInputChangeEditor = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
-        if (typeof e.target.value === 'string') {
-            this.createInputValue = e.target.value;
-        }
-    };
-    removeWhitespace(str: string): string {
-        return str.replace(/\s+/g, '');
-    }
-    autoResize(element: HTMLTextAreaElement): void {
-        element.style.height = '5px';
-        element.style.height = element.scrollHeight + 'px';
-    }
-    timeline = `gantt
-    title College Timeline
-    dateFormat  YYYY-MM-DD
-    section Semester 1
-    Orientation           :done,    des1, 2023-08-01, 2023-08-03
-    Classes Start         :active,  des2, 2023-08-04, 2023-12-15
-    Midterm Exams         :         des3, 2023-10-15, 2023-10-20
-    End of Semester       :         des4, 2023-12-16, 2023-12-20
-    section Semester 2
-    Classes Start         :         des5, 2024-01-10, 2024-05-15
-    Spring Break          :         des6, 2024-03-15, 2024-03-22
-    Midterm Exams         :         des7, 2024-03-25, 2024-03-30
-    Final Exams           :         des8, 2024-05-10, 2024-05-15
-    section Summer Break
-    Internship            :         des9, 2024-06-01, 2024-08-31
-    section Semester 3
-    Classes Start         :         des10, 2024-09-01, 2025-12-15
-    Midterm Exams         :         des11, 2024-11-15, 2024-11-20
-    End of Semester       :         des12, 2025-12-16, 2025-12-20
-    section Semester 4
-    Classes Start         :         des13, 2025-01-10, 2025-05-15
-    Spring Break          :         des14, 2025-03-15, 2025-03-22
-    Midterm Exams         :         des15, 2025-03-25, 2025-03-30
-    Final Exams           :         des16, 2025-05-10, 2025-05-15
-    Graduation            :         des17, 2025-05-20, 2025-05-21`;
 }
 
 Docs.Prototypes.TemplateMap.set(DocumentType.DIAGRAM, {
-- 
cgit v1.2.3-70-g09d2

