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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Syncfusion.Blazor.Diagram" Version="*" />
<PackageReference Include="Syncfusion.Blazor.Themes" Version="*" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" />
<ResourcePreloader />
<link rel="stylesheet" href="@Assets["lib/bootstrap/dist/css/bootstrap.min.css"]" />
<link rel="stylesheet" href="@Assets["app.css"]" />
<link rel="stylesheet" href="@Assets["AnnotationTemplateUndoRedo.styles.css"]" />
<ImportMap />
<link rel="icon" type="image/png" href="favicon.png" />
<link href="_content/Syncfusion.Blazor.Themes/fluent2.css" rel="stylesheet" />
<HeadOutlet @rendermode="InteractiveServer" />
</head>

<body>
<Routes @rendermode="InteractiveServer" />
<ReconnectModal />
<script src="_content/Syncfusion.Blazor.Diagram/scripts/sf-diagramcomponent.min.js" type="text/javascript"></script>
<script src="@Assets["_framework/blazor.web.js"]"></script>
</body>

</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@inherits LayoutComponentBase

<div class="page">
<main>
@Body
</main>
</div>

Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
.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;
}
}

#blazor-error-ui {
color-scheme: light only;
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
box-sizing: border-box;
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
}

#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
@page "/"

@using Syncfusion.Blazor.Diagram
@using Syncfusion.Blazor.Buttons
@using System.Threading.Tasks

<SfButton Content="UpdateAnnotation1" OnClick="@UpdateAnnotation1" />
<SfButton Content="UpdateAnnotation2" OnClick="@UpdateAnnotation2" />
<SfButton Content="Undo" OnClick="@(() => diagram.Undo())" />
<SfButton Content="Redo" OnClick="@(() => diagram.Redo())" />

<SfDiagramComponent Height="600px" @ref="@diagram" Nodes="@nodes">
<DiagramHistoryManager HistoryAdding="@OnHistoryAdding" Undo="@OnCustomUndo" Redo="@OnCustomRedo" />
<DiagramTemplates>
<AnnotationTemplate>
<div>
@{
string? content = context.AdditionalInfo["Content"]?.ToString();
}
@if (!string.IsNullOrEmpty(content))
{
<div class="node-title">@content</div>
}
</div>
</AnnotationTemplate>
</DiagramTemplates>
</SfDiagramComponent>

<style>

.node-title {
font-weight: bold;
font-size: 13px;
color: #1a1a2e;
}

</style>

@code {

private SfDiagramComponent diagram;
private DiagramObjectCollection<Node> nodes;
private bool isAnnotationTemplate = false;

// This event is triggered before a new entry is added to the history stack.
private void OnHistoryAdding(HistoryAddingEventArgs entry)
{
if (isAnnotationTemplate)
{
// The flag is true during a programmatic AdditionalInfo update.
// Cancel the diagram's automatic history entry to prevent duplicates.
entry.Cancel = true;
}
}

// Called when the user performs an Undo action.
private void OnCustomUndo(HistoryEntryBase entry)
{
if (entry.UndoObject != null && entry.UndoObject is Node node)
{
// To prevent property change entry
isAnnotationTemplate = true;

// Restore AdditionalInfo from the undo snapshot (stored on the annotation)
diagram.Nodes?[0].Annotations?[0].AdditionalInfo = new Dictionary<string, object>(node.Annotations?[0].AdditionalInfo);

isAnnotationTemplate = false;
}
}

// Called when the user performs an Redo action.
private void OnCustomRedo(HistoryEntryBase entry)
{
if (entry.RedoObject != null && entry.RedoObject is Node node)
{
// To prevent property change entry
isAnnotationTemplate = true;

// Restore AdditionalInfo from the redo snapshot (stored on the annotation)
diagram.Nodes?[0].Annotations?[0].AdditionalInfo = new Dictionary<string, object>(node.Annotations?[0].AdditionalInfo);

isAnnotationTemplate = false;
}
}

protected override void OnInitialized()
{
InitializeDiagram();
}

private void InitializeDiagram()
{
nodes = new DiagramObjectCollection<Node>();

Dictionary<string, object> annotationInfo = new Dictionary<string, object>
{
{ "Content", "Annotation" },
};

Node node = new Node()
{
ID = "node",
Width = 150,
Height = 120,
OffsetX = 200,
OffsetY = 200,
Annotations = new DiagramObjectCollection<ShapeAnnotation>()
{
new ShapeAnnotation
{
UseTemplate = true,
Width = 150,
Height = 120,
AdditionalInfo = annotationInfo
}
},
Style = new ShapeStyle()
{
Fill = "#6495ED",
StrokeColor = "white"
},
};
nodes.Add(node);
}

private async Task UpdateAnnotationAsync(string content)
{
diagram.BeginUpdate();

HistoryEntry entry = new HistoryEntry();

// Capture the current state (before changes) as the undo snapshot
(entry.UndoObject) = diagram.Nodes?[0].Clone() as Node;

entry.Type = HistoryEntryType.Undo;

// To prevent property change entry
isAnnotationTemplate = true;

// Update AdditionalInfo on the annotation so context.AdditionalInfo reflects it in the template
diagram.Nodes?[0].Annotations?[0].AdditionalInfo = new Dictionary<string, object>
{
{ "Content", content },
};

isAnnotationTemplate = false;

// Capture the updated state as the redo snapshot
(entry.RedoObject) = diagram.Nodes?[0].Clone() as Node;

diagram.AddHistoryEntry(entry);

await diagram.EndUpdateAsync();
}

private void UpdateAnnotation1()
{
_ = UpdateAnnotationAsync("Updated Annotation 1");
}

private void UpdateAnnotation2()
{
_ = UpdateAnnotationAsync("Updated Annotation 2");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<Router AppAssembly="typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
<FocusOnNavigate RouteData="routeData" Selector="h1" />
</Found>
</Router>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using static Microsoft.AspNetCore.Components.Web.RenderMode
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using AnnotationTemplateUndoRedo_Net10
@using AnnotationTemplateUndoRedo_Net10.Components
@using AnnotationTemplateUndoRedo_Net10.Components.Layout
@using Syncfusion.Blazor;
@using Syncfusion.Blazor.Diagram;
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using AnnotationTemplateUndoRedo_Net10.Components;
using Syncfusion.Blazor;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();

builder.Services.AddSyncfusionBlazor();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseStatusCodePagesWithReExecute("/not-found");
app.UseHttpsRedirection();

app.UseAntiforgery();

app.MapStaticAssets();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();

app.Run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5131",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7091;http://localhost:5131",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
Loading