Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:FlowchartSample"
x:Class="FlowchartSample.App">
<Application.Resources>
<ResourceDictionary>

<!--
For information about styling .NET MAUI pages
please refer to the documentation:
https://go.microsoft.com/fwlink/?linkid=2282329
-->

</ResourceDictionary>
</Application.Resources>
</Application>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace FlowchartSample
{
public partial class App : Application
{
public App()
{
InitializeComponent();
}

protected override Window CreateWindow(IActivationState? activationState)
{
return new Window(new MainPage()) { Title = "FlowchartSample" };
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@inherits LayoutComponentBase

<div class="page">
<main>
@Body
</main>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
.page {
position: relative;
display: flex;
flex-direction: column;
}

main {
flex: 1;
}

.sidebar {
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
}

.top-row {
background-color: #f7f7f7;
border-bottom: 1px solid #d6d5d5;
justify-content: flex-end;
height: 3.5rem;
display: flex;
align-items: center;
}

.top-row ::deep a, .top-row ::deep .btn-link {
white-space: nowrap;
margin-left: 1.5rem;
text-decoration: none;
}

.top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
text-decoration: underline;
}

.top-row ::deep a:first-child {
overflow: hidden;
text-overflow: ellipsis;
}

@media (max-width: 640.98px) {
.top-row {
justify-content: space-between;
}

.top-row ::deep a, .top-row ::deep .btn-link {
margin-left: 0;
}
}

@media (min-width: 641px) {
.page {
flex-direction: row;
}

.sidebar {
width: 250px;
height: 100vh;
position: sticky;
top: 0;
}

.top-row {
position: sticky;
top: 0;
z-index: 1;
}

.top-row.auth ::deep a:first-child {
flex: 1;
text-align: right;
width: 0;
}

.top-row, article {
padding-left: 2rem !important;
padding-right: 1.5rem !important;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using Microsoft.Extensions.AI;
using Syncfusion.Blazor.AI;
using System;


namespace AIService
{
public class AzureAIService
{
private IChatClient _chatClient;

public AzureAIService(IChatClient client)
{
this._chatClient = client ?? throw new ArgumentNullException(nameof(client));
}


/// <summary>
/// Gets a text completion from the Azure OpenAI service.
/// </summary>
/// <param name="prompt">The user prompt to send to the AI service.</param>
/// <param name="returnAsJson">Indicates whether the response should be returned in JSON format. Defaults to <c>true</c></param>
/// <param name="systemRole">Specifies the systemRole that is sent to AI Clients. Defaults to <c>null</c></param>
/// <returns>The AI-generated completion as a string.</returns>
public async Task<string> GetCompletionAsync(string prompt, bool returnAsJson = true, string systemRole = null, int outputTokens = 2000)
{
string systemMessage = returnAsJson ? "You are a helpful assistant that only returns and replies with valid, iterable RFC8259 compliant JSON in your responses unless I ask for any other format. Do not provide introductory words such as 'Here is your result' or '```json', etc. in the response" : !string.IsNullOrEmpty(systemRole) ? systemRole : "You are a helpful assistant";
try
{
ChatParameters chatParameters = new ChatParameters();
chatParameters.Messages = new List<ChatMessage>(2) {
new ChatMessage (ChatRole.System, systemMessage),
new ChatMessage(ChatRole.User,prompt),
};
string completion = await GetChatResponseAsync(chatParameters);
return completion;
}
catch (Exception ex)
{
Console.WriteLine($"An exception has occurred: {ex.Message}");
return "";
}
}

public async Task<string> GetChatResponseAsync(ChatParameters options)
{
ChatOptions completionRequest = new ChatOptions
{
Temperature = options.Temperature ?? 0.5f,
TopP = options.TopP ?? 1.0f,
MaxOutputTokens = options.MaxTokens ?? 2000,
FrequencyPenalty = options.FrequencyPenalty ?? 0.0f,
PresencePenalty = options.PresencePenalty ?? 0.0f,
StopSequences = options.StopSequences
};
try
{
ChatResponse completion = await _chatClient.GetResponseAsync(options.Messages, completionRequest);
return completion.Text.ToString();
}
catch (Exception ex)
{
throw;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
@using Syncfusion.Blazor.Buttons
@using Syncfusion.Blazor.Popups
@using Syncfusion.Blazor.Inputs
@using TextToFlowchartDiagram
@using AIService
@inject AzureAIService ChatGptService
@namespace TextToFlowchartDiagram

<SfFab IconCss="e-icons e-ai-chat" Content="AI Assist" OnClick="OnFabClicked" Target="#diagram-space"></SfFab>
<SfDialog Width="570px" IsModal="true" ShowCloseIcon="true" CssClass="custom-dialog" Visible="@ShowAIAssistDialog">
<DialogTemplates>
<Header> <span class="e-icons e-ai-chat" style="color: black; font-size: 16px;"></span> AI Assist</Header>
<Content>
<p style="margin-bottom: 10px;">Suggested Prompts</p>
<SfButton style="flex: 1; overflow: visible; border-radius: 8px;margin-bottom: 10px;" @onclick="()=>GenerateMindMap(ShoppingPrompt)">Flowchart diagram for Online shopping process</SfButton>
<SfButton style="flex: 1; overflow: visible; border-radius: 8px;margin-bottom: 10px;" @onclick="()=>GenerateMindMap(TravelBookingPrompt)">Flowchart diagram for Travel booking system</SfButton>
<SfButton style="flex: 1; overflow: visible; border-radius: 8px;margin-bottom: 10px;" @onclick="()=>GenerateMindMap(SoftwareLifecyclePrompt)">Flowchart diagram for Software development lifecycle</SfButton>

<div style="display: flex; flex: 95%; margin-top:20px;">
<SfTextBox @bind-Value="@OpenAIPrompt" CssClass="db-openai-textbox" Height="32px" Placeholder="Please enter your prompt for generating a flowchart diagram..." autofocus style="font-size: 14px;"></SfTextBox>
<SfButton @onclick="@GenerateDiagramFromAI" CssClass="e-icons e-flat e-send" IsPrimary="true" style="height: 38px; width: 38px; margin-left: 5px; padding: 0;"></SfButton>
</div>
</Content>
</DialogTemplates>
<DialogEvents Closed="@DialogClose"></DialogEvents>
</SfDialog>

Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace TextToFlowchartDiagram
{
public partial class FlowchartDiagramOpenAI
{
#pragma warning disable CS8618
public bool ShowAIAssistDialog = false;
public string OpenAIPrompt;
public Home Parent;
string ShoppingPrompt = "Online Shopping Process";
string TravelBookingPrompt = "Travel Booking System";
string SoftwareLifecyclePrompt = "Software Development Lifecycle";
#pragma warning restore CS8618
public void OnFabClicked()
{
ShowAIAssistDialog = !ShowAIAssistDialog;
}
private void DialogClose(Object args)
{
ShowAIAssistDialog = false;
}
public async void GenerateMindMap(string value)
{
OpenAIPrompt = value;
await GenerateDiagramFromAI();
StateHasChanged();
}
public async Task GenerateDiagramFromAI()
{
ShowAIAssistDialog = false;
Parent.IsGeneratingFromAI = true;
if (!string.IsNullOrWhiteSpace(OpenAIPrompt))
{
await Parent.SpinnerRef!.ShowAsync();
string result = string.Empty;
string systemRole = "You are an expert assistant skilled in generating Mermaid flowchart diagram data based on user queries.";

string userRole = $@"Create a Mermaid flowchart code for a process titled: {OpenAIPrompt}. The flowchart should include decision points with 'Yes' or 'No' branches.

Use the format provided in the example below, adapting the steps, conditions, and styles to match the new title:

**Example Title:** Bus Ticket Booking

**Example Mermaid Code:**

graph TD
A([Start]) --> B[Choose Destination]
B --> C{{Already Registered?}}
C -->|No| D[Sign Up]
D --> E[Enter Details]
E --> F[Search Buses]
C --> |Yes| F
F --> G{{Buses Available?}}
G -->|Yes| H[Select Bus]
H --> I[Enter Passenger Details]
I --> J[Make Payment]
J --> K[Booking Confirmed]
G -->|No| L[Set Reminder]
K --> M([End])
L --> M
style A fill:#90EE90,stroke:#333,stroke-width:2px;
style B fill:#4682B4,stroke:#333,stroke-width:2px;
style C fill:#32CD32,stroke:#333,stroke-width:2px;
style D fill:#FFD700,stroke:#333,stroke-width:2px;
style E fill:#4682B4,stroke:#333,stroke-width:2px;
style F fill:#4682B4,stroke:#333,stroke-width:2px;
style G fill:#32CD32,stroke:#333,stroke-width:2px;
style H fill:#4682B4,stroke:#333,stroke-width:2px;
style I fill:#4682B4,stroke:#333,stroke-width:2px;
style J fill:#4682B4,stroke:#333,stroke-width:2px;
style K fill:#FF6347,stroke:#333,stroke-width:2px;
style L fill:#FFD700,stroke:#333,stroke-width:2px;
style M fill:#FF6347,stroke:#333,stroke-width:2px;

**Instructions:** Ensure the generated flowchart code is specific to the title '{OpenAIPrompt}' and adheres to the provided format. Every node **must include a corresponding `style` line** to avoid default white backgrounds. Do not include any additional text, explanations, or comments—only the Mermaid flowchart code.";

result = await ChatGptService.GetCompletionAsync(userRole, false, systemRole);
if (result != null)
{
List<string> lines = result.Split(new[] { "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries).ToList();
lines = lines.Where(line => !line.Contains("```")).ToList();
int startIndex = lines.FindIndex(line => line.Trim().StartsWith("graph TD"));
if (startIndex != -1)
{
List<string> validMermaidData = lines.Skip(startIndex).ToList();
result = string.Join(Environment.NewLine, validMermaidData);
await Parent.Diagram!.LoadDiagramFromMermaidAsync(result);
}
else
await GenerateDiagramFromAI();
StateHasChanged();
}
await Parent.SpinnerRef.HideAsync();
}
Parent.IsGeneratingFromAI = false;
}
}
}
Loading