GraphView.razor 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. @inject IJSRuntime JS
  2. @implements IAsyncDisposable
  3. <div class="bg-zinc-900/40 overflow-auto h-full w-full"
  4. data-testid="@(TestId ?? "graph-view")">
  5. @if (_isRendering)
  6. {
  7. <div class="text-zinc-500 text-sm p-4">rendering diagram…</div>
  8. }
  9. else if (_error is not null)
  10. {
  11. <div class="text-red-400 text-sm p-4 font-mono whitespace-pre-wrap">@_error</div>
  12. }
  13. <div id="@HostId" class="p-2"></div>
  14. </div>
  15. @code {
  16. [Parameter] public string? Source { get; set; }
  17. [Parameter] public string? TestId { get; set; }
  18. /// <summary>
  19. /// The id of the host element holding the rendered SVG. Defaults to a
  20. /// random GUID per instance; pages that need to call SVG-export JS on
  21. /// this view should pass a stable id.
  22. /// </summary>
  23. [Parameter] public string? Id { get; set; }
  24. private string HostId => Id ?? _generatedId;
  25. private readonly string _generatedId = $"rpkg-host-{Guid.NewGuid():N}";
  26. private string? _renderedSource;
  27. private bool _isRendering;
  28. private string? _error;
  29. protected override async Task OnAfterRenderAsync(bool firstRender)
  30. {
  31. // Re-render only when the source actually changes — Blazor calls
  32. // OnAfterRender on every state change.
  33. if (Source == _renderedSource) return;
  34. _renderedSource = Source;
  35. if (string.IsNullOrWhiteSpace(Source))
  36. {
  37. try
  38. {
  39. await JS.InvokeVoidAsync("rackpeekGraph.render", HostId, "");
  40. }
  41. catch
  42. {
  43. // Ignore — the host may not be ready / the page is unloading.
  44. }
  45. return;
  46. }
  47. _isRendering = true;
  48. _error = null;
  49. StateHasChanged();
  50. try
  51. {
  52. await JS.InvokeVoidAsync("rackpeekGraph.render", HostId, Source);
  53. }
  54. catch (Exception ex)
  55. {
  56. _error = $"Diagram render failed: {ex.Message}";
  57. }
  58. finally
  59. {
  60. _isRendering = false;
  61. StateHasChanged();
  62. }
  63. }
  64. public async ValueTask DisposeAsync()
  65. {
  66. try
  67. {
  68. await JS.InvokeVoidAsync("rackpeekGraph.render", HostId, "");
  69. }
  70. catch
  71. {
  72. // ignore on teardown
  73. }
  74. }
  75. }