aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/apis/gpt/GPT.ts6
-rw-r--r--src/client/views/nodes/DiagramBox.tsx207
2 files changed, 128 insertions, 85 deletions
diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts
index fb51278ae..49c56f04e 100644
--- a/src/client/apis/gpt/GPT.ts
+++ b/src/client/apis/gpt/GPT.ts
@@ -4,6 +4,7 @@ enum GPTCallType {
SUMMARY = 'summary',
COMPLETION = 'completion',
EDIT = 'edit',
+ MERMAID='mermaid'
}
type GPTCallOpts = {
@@ -17,8 +18,10 @@ const callTypeMap: { [type: string]: GPTCallOpts } = {
summary: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: 'Summarize this text in simpler terms: ' },
edit: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: 'Reword this: ' },
completion: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: '' },
+ mermaid:{model:'gpt-3.5-turbo-instruct',maxTokens:256,temp:0,prompt:"Write this in mermaid code (keep in note thatPut this at the end of the code to add colors heres an example and be very care about the order:pie title Example Pie Chart \"Red\" : 25 \"Blue\" : 75%%{init: {'theme': 'base', 'themeVariables': { 'pie1': '#0000FF', 'pie2': '#FF0000'}}}%%): "}
};
+
/**
* Calls the OpenAI API.
*
@@ -30,7 +33,7 @@ const gptAPICall = async (inputText: string, callType: GPTCallType) => {
const opts: GPTCallOpts = callTypeMap[callType];
try {
const configuration: ClientOptions = {
- apiKey: process.env.OPENAI_KEY,
+ apiKey: "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",
dangerouslyAllowBrowser: true,
};
const openai = new OpenAI(configuration);
@@ -39,6 +42,7 @@ const gptAPICall = async (inputText: string, callType: GPTCallType) => {
max_tokens: opts.maxTokens,
temperature: opts.temp,
prompt: `${opts.prompt}${inputText}`,
+
});
return response.choices[0].text;
} catch (err) {
diff --git a/src/client/views/nodes/DiagramBox.tsx b/src/client/views/nodes/DiagramBox.tsx
index 3b9e9d952..64d0d6d78 100644
--- a/src/client/views/nodes/DiagramBox.tsx
+++ b/src/client/views/nodes/DiagramBox.tsx
@@ -1,4 +1,4 @@
-import { makeObservable, observable } from 'mobx';
+import { makeObservable, observable, action } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { ViewBoxAnnotatableComponent, ViewBoxInterface } from '../DocComponent';
@@ -10,10 +10,11 @@ import mermaid from 'mermaid';
import { Doc, DocListCast } from '../../../fields/Doc';
import { List } from '../../../fields/List';
import { RichTextField } from '../../../fields/RichTextField';
+import { ContextMenu } from '../ContextMenu';
+import { gptAPICall, GPTCallType } from '../../apis/gpt/GPT';
@observer
export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implements ViewBoxInterface {
-
public static LayoutString(fieldKey: string) {
return FieldView.LayoutString(DiagramBox, fieldKey);
}
@@ -26,7 +27,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() im
componentDidMount() {
this._props.setContentViewBox?.(this);
mermaid.initialize({
- securityLevel: "loose",
+ securityLevel: 'loose',
startOnLoad: true,
flowchart: { useMaxWidth: true, htmlLabels: true, curve: 'cardinal' },
});
@@ -36,110 +37,148 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() im
const { svg, bindFunctions } = await mermaidDiagram(str);
return { svg, bindFunctions };
} catch (error) {
- console.error("Error rendering mermaid diagram:", error);
- return { svg: "", bindFunctions: undefined };
+ console.error('Error rendering mermaid diagram:', error);
+ return { svg: '', bindFunctions: undefined };
}
};
const mermaidDiagram = async (str: string) => {
- return await mermaid.render("graph" + Date.now(), str);
+ 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);
+ async function renderMermaidAsync(this: DiagramBox) {
+ try {
+ const mermaidCode: string = await this.createMermaidCode();
+ const { svg, bindFunctions } = await renderMermaid(mermaidCode);
+ const dashDiv = document.getElementById('dashDiv');
+ if (dashDiv) {
+ dashDiv.innerHTML = svg;
+ if (bindFunctions) {
+ bindFunctions(dashDiv);
+ }
}
+ } catch (error) {
+ console.error('Error rendering Mermaid:', error);
}
- });
+ }
+
+ renderMermaidAsync.call(this);
}
- 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)+ ';';
+
+ askGPT = async (): Promise<string | undefined> => {
+ try {
+ let notes = 'mermaid syntax for pie charts do not include %';
+ let text = notes + (DocListCast(this.Document.data)[0].text as RichTextField)?.Text;
+ if (!text) {
+ console.error('Text extraction failed');
+ return;
+ }
+
+ let res = await gptAPICall(text, GPTCallType.MERMAID);
+ if (!res) {
+ console.error('GPT call failed');
+ return;
+ } else {
+ console.log(res)
+ return this.removeWords(res);
+ }
+ } catch (err) {
+ console.error('Error:', err);
+ return;
+ }
+ };
+
+ removeWords(inputStr:string) {
+ let presetArray=["pie","flowchart","diagramChart","graph TD","flowchart TD","flowchart LR","graph LR"]
+ const lines = inputStr.split('\n');
+ let foundPresetWord = false;
+ let result = '';
+
+ for (const line of lines) {
+ if (!foundPresetWord) {
+ for (const word of presetArray) {
+ if (line.toLowerCase().includes(word.toLowerCase())) {
+ foundPresetWord = true;
+ result += line + '\n';
+ break;
+ }
+ }
+ } else {
+ result += line + '\n';
+ }
+ }
+
+ return result;
+ }
+
+ createMermaidCode = async (): Promise<string> => {
+ let mermaidCode = '';
+ let docArray: Doc[] = DocListCast(this.Document.data);
+ if (docArray.length === 1) {
+ if (docArray[0].type == 'rich text') {
+ const gptResponse = await this.askGPT();
+ console.log(gptResponse);
+ if (gptResponse) {
+ mermaidCode = gptResponse;
+ }
+ }
+ } else {
+ 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);
+ //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+")"
+ };
+
+ 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+"))"
+ 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 '( )';
+ };
+ 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{
+ };
+ 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>
- );
+ return <div id="dashDiv" className="diagramBox"></div>;
}
}
-