diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/.DS_Store | bin | 10244 -> 10244 bytes | |||
-rw-r--r-- | src/client/documents/DocumentTypes.ts | 1 | ||||
-rw-r--r-- | src/client/documents/Documents.ts | 14 | ||||
-rw-r--r-- | src/client/util/CurrentUserUtils.ts | 9 | ||||
-rw-r--r-- | src/client/views/nodes/DiagramBox.scss | 0 | ||||
-rw-r--r-- | src/client/views/nodes/DiagramBox.tsx | 145 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentContentsView.tsx | 2 |
7 files changed, 169 insertions, 2 deletions
diff --git a/src/.DS_Store b/src/.DS_Store Binary files differindex f8d745dbf..e1d584ba0 100644 --- a/src/.DS_Store +++ b/src/.DS_Store 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, |