Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Json specific code editor component #158

Merged
merged 1 commit into from
Feb 28, 2024
Merged
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
20 changes: 20 additions & 0 deletions src/modules/Elsa.Studio.UIHints/Components/Json.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
@using BlazorMonaco.Editor

@{
var inputDescriptor = EditorContext.InputDescriptor;
var displayName = inputDescriptor.DisplayName;
var description = inputDescriptor.Description;
}

<ExpressionInput EditorContext="@EditorContext">
<ChildContent>
<MudField Variant="Variant.Outlined" Label="@displayName" HelperText="@description" Margin="Margin.Dense">
<StandaloneCodeEditor
@ref="_monacoEditor"
Id="@_monacoEditorId"
ConstructionOptions="ConfigureMonacoEditor"
CssClass="studio-expression-input-monaco-editor studio-monaco-editor-large"
OnDidChangeModelContent="OnMonacoContentChanged"/>
</MudField>
</ChildContent>
</ExpressionInput>
91 changes: 91 additions & 0 deletions src/modules/Elsa.Studio.UIHints/Components/Json.razor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
using BlazorMonaco.Editor;
using Elsa.Api.Client.Resources.Scripting.Models;
using Elsa.Api.Client.Shared.UIHints.CodeEditor;
using Elsa.Studio.Extensions;
using Elsa.Studio.Models;
using Elsa.Studio.UIHints.Extensions;
using Microsoft.AspNetCore.Components;
using ThrottleDebounce;

namespace Elsa.Studio.UIHints.Components;

/// <summary>
/// A component that renders a code editor.
/// </summary>
public partial class Json : IDisposable
{
private readonly string _monacoEditorId = $"monaco-editor-{Guid.NewGuid()}:N";
private StandaloneCodeEditor? _monacoEditor;
private string? _lastMonacoEditorContent;
private readonly RateLimitedFunc<Task> _throttledValueChanged;
private CodeEditorOptions _codeEditorOptions = new();

/// <inheritdoc />
public Json()
{
_throttledValueChanged = Debouncer.Debounce(InvokeValueChangedCallback, TimeSpan.FromMilliseconds(500));
}

/// <summary>
/// The context for the editor.
/// </summary>
[Parameter] public DisplayInputEditorContext EditorContext { get; set; } = default!;

private string InputValue => EditorContext.GetLiteralValueOrDefault();

/// <inheritdoc />
protected override void OnInitialized()
{
_codeEditorOptions = EditorContext.InputDescriptor.GetCodeEditorOptions();
}

private StandaloneEditorConstructionOptions ConfigureMonacoEditor(StandaloneCodeEditor editor)
{
var language = _codeEditorOptions.Language ?? "javascript";

return new StandaloneEditorConstructionOptions
{
Language = language,
Value = InputValue,
FontFamily = "Roboto Mono, monospace",
RenderLineHighlight = "none",
Minimap = new EditorMinimapOptions
{
Enabled = false
},
AutomaticLayout = true,
LineNumbers = "on",
Theme = "vs",
RoundedSelection = true,
ScrollBeyondLastLine = false,
ReadOnly = false,
OverviewRulerLanes = 0,
OverviewRulerBorder = false,
LineDecorationsWidth = 0,
HideCursorInOverviewRuler = true,
GlyphMargin = false
};
}

private async Task OnMonacoContentChanged(ModelContentChangedEvent e)
{
await _throttledValueChanged.InvokeAsync();
}

private async Task InvokeValueChangedCallback()
{
var value = await _monacoEditor!.GetValue();

// This event gets fired even when the content hasn't changed, but for example when the containing pane is resized.
// This happens from within the monaco editor itself (or the Blazor wrapper, not sure).
if (value == _lastMonacoEditorContent)
return;

_lastMonacoEditorContent = value;
var expression = Expression.CreateLiteral(value);

await InvokeAsync(async () => await EditorContext.UpdateExpressionAsync(expression));
}

void IDisposable.Dispose() => _throttledValueChanged.Dispose();
}
4 changes: 2 additions & 2 deletions src/modules/Elsa.Studio.UIHints/Handlers/JsonEditorHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ public RenderFragment DisplayInputEditor(DisplayInputEditorContext context)
{
return builder =>
{
builder.OpenComponent(0, typeof(Code));
builder.AddAttribute(1, nameof(Code.EditorContext), context);
builder.OpenComponent(0, typeof(Json));
builder.AddAttribute(1, nameof(Json.EditorContext), context);
builder.CloseComponent();
};
}
Expand Down
Loading