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,30 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>$(DefineConstants)TRACE;SERVER</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DefineConstants>$(DefineConstants)TRACE;SERVER</DefineConstants>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
<None Include="Shared\MainLayout.razor" />
<None Include="wwwroot\interop.js" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.*" />
<PackageReference Include="StackExchange.Redis" Version="*" />
<PackageReference Include="Syncfusion.Blazor" Version="32.1.19" />
</ItemGroup>


</Project>

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System.Text.Json.Serialization;
using System.ComponentModel.DataAnnotations;

namespace DiagramServer.Models
{
// Lightweight rectangle model to avoid external DiagramRect dependency
public class DiagramRect
{
public double X { get; set; }
public double Y { get; set; }
public double Width { get; set; }
public double Height { get; set; }
}
public class DiagramData
{
public string DiagramId { get; set; } = string.Empty;
public string Data { get; set; } = string.Empty;
public long Version { get; set; } = 1;
}
public class DiagramUpdateMessage
{
[JsonPropertyName("sourceConnectionId")]
public string SourceConnectionId { get; set; } = string.Empty;
[JsonPropertyName("modifiedElements")]
public List<string>? ModifiedElementIds { get; set; }
[JsonPropertyName("version")]
public long Version { get; set; }
}
public class DiagramUser
{
public string ConnectionId { get; set; } = string.Empty;
public string UserName { get; set; } = string.Empty;
}
public sealed class SelectionEvent
{
public string ConnectionId { get; set; } = default!;
public string? UserId { get; set; }
public string? UserName { get; set; }
public List<string> ElementIds { get; set; } = new();
public long TimestampUnixMs { get; set; }
public SelectorBounds? SelectorBounds { get; set; }
}
public class SelectorBounds
{
public DiagramServer.Models.DiagramRect? Bounds { get; set; }
public double RotationAngle { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="NuGet.org" value="https://api.nuget.org/v3/index.json" />
<!-- Resources -->
</packageSources>
<config>
<add key="dependencyVersion" value="Highest" />
</config>
</configuration>

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
@using Syncfusion.Blazor.Notifications
@namespace DiagramCollaboration

<SfToast @ref="ToastObj" Width="400px" ShowCloseButton="true">
<ToastPosition X="Right" Y="Top"></ToastPosition>
</SfToast>

@code
{
public SfToast ToastObj;
public string ToastContent { get; set; }

internal async Task ShowToastAsync(string message)
{
ToastObj.Content = message;
await this.ToastObj.ShowAsync();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Microsoft.JSInterop;
using System;
using System.Threading.Tasks;

namespace DiagramCollaboration
{

#pragma warning disable CA1052 // Static holder types should be Static or NotInheritable
public class FileUtil
#pragma warning restore CA1052 // Static holder types should be Static or NotInheritable
{
public async static Task SaveAs(IJSRuntime js, string data, string fileName)
{
await js.InvokeAsync<object>(
"saveDiagram",
#pragma warning disable CA1305 // Specify IFormatProvider
Convert.ToString(data), fileName).ConfigureAwait(true);
#pragma warning restore CA1305 // Specify IFormatProvider
}
public async static Task Click(IJSRuntime js)
{
await js.InvokeAsync<object>(
"click").ConfigureAwait(true);
}
public async static Task<string> LoadFile(IJSRuntime js, object data)
{
return await js.InvokeAsync<string>(
"loadFile", data).ConfigureAwait(true);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using Microsoft.Extensions.Logging;
using DiagramServer.Models;

namespace DiagramServer.Services
{
public class DiagramService : IDiagramService
{
private readonly IRedisService _redis;
private readonly ILogger<DiagramService> _logger;

private const string DIAGRAM_KEY_PREFIX = "diagramData:";

public DiagramService(IRedisService redis, ILogger<DiagramService> logger)
{
_redis = redis;
_logger = logger;
}

public async Task<DiagramData?> GetDiagramAsync(string diagramId)
{
try
{
var key = $"{DIAGRAM_KEY_PREFIX}{diagramId}";
var diagramData = await _redis.GetAsync<DiagramData>(key);

if (diagramData != null)
{
_logger.LogDebug("Retrieved diagram {DiagramId}", diagramId);
}

return diagramData;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving diagram {DiagramId}", diagramId);
return null;
}
}
public async Task<bool> SaveDiagramDataAsync(string diagramId, string data, string userId)
{
try
{
var diagramData = new DiagramData
{
DiagramId = diagramId,
Data = data,
};

var key = $"{DIAGRAM_KEY_PREFIX}{diagramId}";
var success = await _redis.SetAsync(key, diagramData);

if (success)
{
_logger.LogInformation($"Saved diagram by user {userId} with provided data");
}

return success;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error saving diagram {DiagramId}", diagramId);
return false;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using DiagramServer.Models;

namespace DiagramServer.Services
{
public interface IDiagramService
{
Task<DiagramData?> GetDiagramAsync(string diagramId);
Task<bool> SaveDiagramDataAsync(string diagramId, string diagramData, string userId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using StackExchange.Redis;

namespace DiagramServer.Services
{
public interface IRedisService
{
Task<T?> GetAsync<T>(string key);
Task<bool> SetAsync<T>(string key, T value, TimeSpan? expiry = null);
Task<bool> DeleteAsync(string key);
Task<long> ListPushAsync<T>(string key, T value);
Task<(bool accepted, long version)> CompareAndIncrementAsync(string key, long expectedVersion);
Task<long> ListLengthAsync(string key);
Task<RedisValue[]> ListRangeAsync(string key, long start = 0, long stop = -1);
Task<bool> ListTrimAsync(string key, long start, long stop);
Task<List<T>> GetByPatternAsync<T>(string pattern);
}
}
Loading