aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.DS_Storebin10244 -> 10244 bytes
-rw-r--r--src/client/documents/DocumentTypes.ts1
-rw-r--r--src/client/documents/Documents.ts14
-rw-r--r--src/client/util/CurrentUserUtils.ts9
-rw-r--r--src/client/views/nodes/DiagramBox.scss0
-rw-r--r--src/client/views/nodes/DiagramBox.tsx145
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx2
7 files changed, 169 insertions, 2 deletions
diff --git a/src/.DS_Store b/src/.DS_Store
index f8d745dbf..e1d584ba0 100644
--- a/src/.DS_Store
+++ b/src/.DS_Store
Binary files differ
diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts
index 1123bcac9..570d2e9c8 100644
--- a/src/client/documents/DocumentTypes.ts
+++ b/src/client/documents/DocumentTypes.ts
@@ -12,6 +12,7 @@ export enum DocumentType {
REC = 'recording',
PDF = 'pdf',
INK = 'ink',
+ DIAGRAM='diagram',
SCREENSHOT = 'screenshot',
FONTICON = 'fonticonbox',
SEARCH = 'search', // search query
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 29ec1d19e..668d52e4a 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -53,6 +53,7 @@ import { ScreenshotBox } from '../views/nodes/ScreenshotBox';
import { ScriptingBox } from '../views/nodes/ScriptingBox';
import { TaskCompletionBox } from '../views/nodes/TaskCompletedBox';
import { VideoBox } from '../views/nodes/VideoBox';
+import { DiagramBox } from '../views/nodes/DiagramBox';
import { WebBox } from '../views/nodes/WebBox';
import { CalendarBox } from '../views/nodes/calendarBox/CalendarBox';
import { FormattedTextBox } from '../views/nodes/formattedText/FormattedTextBox';
@@ -274,6 +275,8 @@ export class DocumentOptions {
layout_hideResizeHandles?: BOOLt = new BoolInfo('whether to hide the resize handles when selected');
layout_hideLinkButton?: BOOLt = new BoolInfo('whether the blue link counter button should be hidden');
layout_hideDecorationTitle?: BOOLt = new BoolInfo('whether to suppress the document decortations title when selected');
+ _layout_hideContextMenu?: BOOLt = new BoolInfo('whether the context menu can be shown');
+ layout_diagramEditor?: STRt = new StrInfo("specify the JSX string for a diagram editor view")
layout_hideContextMenu?: BOOLt = new BoolInfo('whether the context menu can be shown');
layout_borderRounding?: string;
_layout_borderRounding?: STRt = new StrInfo('amount of rounding to document view corners');
@@ -685,6 +688,13 @@ export namespace Docs {
},
],
[
+ DocumentType.DIAGRAM,
+ {
+ layout: { view: DiagramBox, dataField: defaultDataKey },
+ options: { _height: 300, _layout_fitWidth: true, layout_nativeDimEditable: true, layout_reflowVertical: true, waitForDoubleClickToClick: 'always', systemIcon: 'BsGlobe' },
+ },
+ ],
+ [
DocumentType.BUTTON,
{
layout: { view: LabelBox, dataField: 'title' },
@@ -1058,7 +1068,9 @@ export namespace Docs {
export function ComparisonDocument(options: DocumentOptions = { title: 'Comparison Box' }) {
return InstanceFromProto(Prototypes.get(DocumentType.COMPARISON), undefined, options);
}
-
+ export function DiagramDocument(options: DocumentOptions = { title: 'bruh box' }) {
+ return InstanceFromProto(Prototypes.get(DocumentType.DIAGRAM), undefined, options);
+ }
export function AudioDocument(url: string, options: DocumentOptions = {}, overwriteDoc?: Doc) {
return InstanceFromProto(Prototypes.get(DocumentType.AUDIO), new AudioField(url), options, undefined, undefined, undefined, overwriteDoc);
}
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 38ebc86e7..21b74e30c 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -32,6 +32,7 @@ import { ScriptingGlobals } from "./ScriptingGlobals";
import { ColorScheme } from "./SettingsManager";
import { SnappingManager } from "./SnappingManager";
import { UndoManager } from "./UndoManager";
+import { CollectionView } from "../views/collections/CollectionView";
import { LabelBox } from "../views/nodes/LabelBox";
import { ImageBox } from "../views/nodes/ImageBox";
@@ -349,6 +350,8 @@ pie title Minerals in my tap water
{key: "Collection", creator: opts => Docs.Create.FreeformDocument([], opts), opts: { _width: 150, _height: 100, _layout_fitWidth: true }},
{key: "Webpage", creator: opts => Docs.Create.WebDocument("",opts), opts: { _width: 400, _height: 512, _nativeWidth: 850, data_useCors: true, }},
{key: "Comparison", creator: Docs.Create.ComparisonDocument, opts: { _width: 300, _height: 300 }},
+ {key: "Diagram", creator: Docs.Create.DiagramDocument, opts: { _width: 300, _height: 300, _type_collection: CollectionViewType.Freeform, layout_diagramEditor: CollectionView.LayoutString("data") }, scripts: { onPaint: `toggleDetail(documentView, "diagramEditor","")`}},
+ {key: "Audio", creator: opts => Docs.Create.AudioDocument(nullAudio, opts),opts: { _width: 200, _height: 100, }},
{key: "Audio", creator: opts => Docs.Create.AudioDocument(nullAudio, opts),opts: { _width: 200, _height: 100, _layout_fitWidth: true, }},
{key: "Map", creator: opts => Docs.Create.MapDocument([], opts), opts: { _width: 800, _height: 600, _layout_fitWidth: true, }},
{key: "Screengrab", creator: Docs.Create.ScreenshotDocument, opts: { _width: 400, _height: 200 }},
@@ -369,7 +372,10 @@ pie title Minerals in my tap water
{key: "Plotly", creator: plotlyView, opts: { _width: 300, _height: 300, }},
];
- emptyThings.forEach(thing => DocUtils.AssignDocField(doc, "empty"+thing.key, (opts) => thing.creator(opts), {...standardOps(thing.key), ...thing.opts}, undefined, thing.scripts, thing.funcs));
+ emptyThings.forEach(
+ thing =>{ DocUtils.AssignDocField(doc, "empty"+thing.key, (opts) => thing.creator(opts), {...standardOps(thing.key), ...thing.opts}, undefined, thing.scripts, thing.funcs);
+ console.log(thing.key)
+ });
return [
{ toolTip: "Tap or drag to create a note", title: "Note", icon: "sticky-note", dragFactory: doc.emptyNote as Doc, clickFactory: DocCast(doc.emptyNote)},
@@ -383,6 +389,7 @@ pie title Minerals in my tap water
{ 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)},
+ { toolTip: "Tap or drag to create a diagram", title: "Diagram", icon: "tree", dragFactory: doc.emptyDiagram as Doc, clickFactory: DocCast(doc.emptyDiagram)},
{ toolTip: "Tap or drag to create an audio recorder", title: "Audio", icon: "microphone", dragFactory: doc.emptyAudio as Doc, clickFactory: DocCast(doc.emptyAudio), openFactoryLocation: OpenWhere.overlay},
{ toolTip: "Tap or drag to create a map", title: "Map", icon: "map-marker-alt", dragFactory: doc.emptyMap as Doc, clickFactory: DocCast(doc.emptyMap)},
{ toolTip: "Tap or drag to create a screen grabber", title: "Grab", icon: "photo-video", dragFactory: doc.emptyScreengrab as Doc, clickFactory: DocCast(doc.emptyScreengrab), openFactoryLocation: OpenWhere.overlay, funcs: { hidden: "IsNoviceMode()"}},
diff --git a/src/client/views/nodes/DiagramBox.scss b/src/client/views/nodes/DiagramBox.scss
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/client/views/nodes/DiagramBox.scss
diff --git a/src/client/views/nodes/DiagramBox.tsx b/src/client/views/nodes/DiagramBox.tsx
new file mode 100644
index 000000000..3b9e9d952
--- /dev/null
+++ b/src/client/views/nodes/DiagramBox.tsx
@@ -0,0 +1,145 @@
+import { makeObservable, observable } from 'mobx';
+import { observer } from 'mobx-react';
+import * as React from 'react';
+import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent';
+import { StyleProp } from '../StyleProvider';
+import './DiagramBox.scss';
+import { FieldView, FieldViewProps } from './FieldView';
+import { PinProps, PresBox } from './trails';
+import mermaid from 'mermaid';
+import { Doc, DocListCast } from '../../../fields/Doc';
+import { List } from '../../../fields/List';
+import { RichTextField } from '../../../fields/RichTextField';
+
+@observer
+export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implements ViewBoxInterface {
+
+ public static LayoutString(fieldKey: string) {
+ return FieldView.LayoutString(DiagramBox, fieldKey);
+ }
+ constructor(props: FieldViewProps) {
+ super(props);
+ makeObservable(this);
+ //this.chartContent = 'flowchart LR;A-->B:::wide;B-->C:::wide; B-->D[hello];';
+ }
+
+ componentDidMount() {
+ this._props.setContentViewBox?.(this);
+ mermaid.initialize({
+ securityLevel: "loose",
+ startOnLoad: true,
+ flowchart: { useMaxWidth: true, htmlLabels: true, curve: 'cardinal' },
+ });
+
+ const renderMermaid = async (str: string) => {
+ try {
+ const { svg, bindFunctions } = await mermaidDiagram(str);
+ return { svg, bindFunctions };
+ } catch (error) {
+ console.error("Error rendering mermaid diagram:", error);
+ return { svg: "", bindFunctions: undefined };
+ }
+ };
+ const mermaidDiagram = async (str: string) => {
+ return await mermaid.render("graph" + Date.now(), str);
+ };
+ renderMermaid(this.createMermaidCode()).then(({ svg, bindFunctions }) => {
+ const dashDiv = document.getElementById('dashDiv');
+ if (dashDiv) {
+ dashDiv.innerHTML = svg;
+ if (bindFunctions) {
+ bindFunctions(dashDiv);
+ }
+ }
+ });
+ }
+ createMermaidCode = (): string => {
+ let mermaidCode = 'graph LR;';
+ if (this.Document.data instanceof List) {
+ let docArray: Doc[] = DocListCast(this.Document.data);
+ let rectangleArray = docArray.filter(doc => doc.title == 'rectangle'||doc.title=='circle');
+ let lineArray = docArray.filter(doc => doc.title == 'line' || doc.title == 'stroke');
+ let textArray=docArray.filter(doc=>doc.type=='rich text')
+ for (let i = 0; i < rectangleArray.length; i++) {
+ const rectangle = rectangleArray[i];
+ for (let j = 0; j < lineArray.length; j++) {
+ const line = lineArray[j];
+ if(this.isLineInFirstBox(rectangle,line)){
+ for (let k = 0; k < rectangleArray.length; k++) {
+ const rectangle2 = rectangleArray[k];
+ if (this.isLineInSecondBox(rectangle2, line)&&
+ typeof rectangle.x === 'number' &&
+ typeof rectangle2.x === 'number') {
+ mermaidCode += Math.abs(rectangle.x) +this.getTextInBox(rectangle,textArray) + '---' + Math.abs(rectangle2.x)+ this.getTextInBox(rectangle2,textArray)+ ';';
+ }
+ }
+ }
+ }
+ }
+ }
+ console.log(mermaidCode);
+ return mermaidCode;
+ }
+ getTextInBox=(box: Doc,richTextArray: Doc[]):string=>{
+ for(let i=0;i<richTextArray.length;i++){
+ let textDoc=richTextArray[i]
+ if(typeof textDoc.x==='number'&&
+ typeof textDoc.y==='number'&&
+ typeof box.x==='number'&&
+ typeof box.height==='number'&&
+ typeof box.width==='number'&&
+ typeof box.y==='number'){
+ if(textDoc.x>box.x&&textDoc.x<box.x+box.width&&textDoc.y>box.y&&textDoc.y<box.y+box.height){
+ if(box.title=='rectangle'){
+ return "("+(textDoc.text as RichTextField)?.Text+")"
+ }
+ if(box.title=='circle'){
+ return "(("+(textDoc.text as RichTextField)?.Text+"))"
+ }
+ }
+ }
+ }
+ return "( )";
+ }
+ isLineInFirstBox=(box: Doc,line: Doc):boolean=>{
+ if(
+ typeof line.x === 'number' &&
+ typeof box.x === 'number' &&
+ typeof box.width === 'number' &&
+ typeof box.height === 'number' &&
+ typeof box.y === 'number' &&
+ typeof line.y === 'number') {
+ return line.x < box.x + box.width + (box.width + box.x) * 0.1 &&
+ line.x > box.x &&
+ line.y > box.y &&
+ line.y < box.y + box.height
+ }
+ else{
+ return false;
+ }
+ }
+ isLineInSecondBox=(box:Doc,line:Doc):boolean=>{
+ if (
+ typeof line.x === 'number' &&
+ typeof line.width === 'number' &&
+ typeof box.x === 'number' &&
+ typeof box.width === 'number' &&
+ typeof box.y === 'number' &&
+ typeof box.height === 'number' &&
+ typeof line.y === 'number') {
+ return line.x + line.width > box.x - (box.x - box.width) * 0.1 &&
+ line.x + line.width < box.x + box.width &&
+ line.y > box.y &&
+ line.y < box.y + box.height;
+ }
+ else{
+ return false;
+ }
+ }
+ render() {
+ return (
+ <div id="dashDiv"></div>
+ );
+ }
+}
+
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index e729e2fa2..f32466b8c 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -23,6 +23,7 @@ import { DashWebRTCVideo } from '../webcam/DashWebRTCVideo';
import { YoutubeBox } from './../../apis/youtube/YoutubeBox';
import { AudioBox } from './AudioBox';
import { ComparisonBox } from './ComparisonBox';
+import { DiagramBox } from './DiagramBox';
import { DataVizBox } from './DataVizBox/DataVizBox';
import './DocumentView.scss';
import { EquationBox } from './EquationBox';
@@ -264,6 +265,7 @@ export class DocumentContentsView extends ObservableReactComponent<DocumentConte
DataVizBox,
HTMLtag,
ComparisonBox,
+ DiagramBox,
LoadingBox,
PhysicsSimulationBox,
SchemaRowBox,