Skip to content

Commit

Permalink
PDForm - Added Monaco editor support for string fields.
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkGoldring committed May 28, 2024
1 parent 362dc97 commit 7170b72
Show file tree
Hide file tree
Showing 19 changed files with 328 additions and 35 deletions.
18 changes: 18 additions & 0 deletions PanoramicData.Blazor.Demo/Data/DatabaseQueryModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace PanoramicData.Blazor.Demo.Data;

public class DatabaseQueryModel
{
[Display(Name = "Email Address")]
public string EmailAddress { get; set; } = string.Empty;

[Display(Name = "Frequency Period")]
public TimePeriods FrequencyPeriod { get; set; } = TimePeriods.Week;

[Display(Name = "Frequency Unit")]
[Range(1, 99)]
public ushort FrequencyUnit { get; set; } = 1;

[Display(Name = "SQL Query")]
[MaxLength(10000)]
public string SqlQuery { get; set; } = string.Empty;
}
63 changes: 63 additions & 0 deletions PanoramicData.Blazor.Demo/Pages/PDFormPage5.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
@page "/pdform5"
@using PanoramicData.Blazor.Demo.Data

<h1>PDForm</h1>

<DemoSourceView SourceFiles="Pages/PDFormPage5.razor, Pages/PDFormPage5.razor.cs, Pages/PDFormPage5.razor.css">

<PDToolbar>
<PDToolbarButton Click="OnBeginEditAsync"
CssClass="btn-primary"
IsEnabled="_queryForm?.Mode == FormModes.ReadOnly"
Text="Edit" />
</PDToolbar>

<div class="d-flex">

<PDForm @ref="_queryForm"
CssClass="w-100"
TItem="DatabaseQueryModel"
Item="_model"
DefaultMode="FormModes.ReadOnly"
DataProvider="_dataProvider">

<PDFormHeader TItem="DatabaseQueryModel"
EditTitle="Edit Query" />

<PDFormBody TItem="DatabaseQueryModel">

<PDField TItem="DatabaseQueryModel"
Field="x => x.EmailAddress"
Group="Email"
Label="Email Address" />

<PDField TItem="DatabaseQueryModel"
Field="x => x.FrequencyUnit"
Group="Frequency" />

<PDField TItem="DatabaseQueryModel"
Field="x => x.FrequencyPeriod"
Group="Frequency" />

<PDField TItem="DatabaseQueryModel"
DisplayOptions="QueryEditorOptions"
Field="x => x.SqlQuery"
ShowCopyButton="_ => true" />

</PDFormBody>

<PDFormFooter TItem="DatabaseQueryModel"
Click="OnFooterClick"
SaveButtonText="Save"
ShowCancelWhenReadOnly="false"
ShowDelete="false" />

</PDForm>

</div>

</DemoSourceView>

<style>
</style>
61 changes: 61 additions & 0 deletions PanoramicData.Blazor.Demo/Pages/PDFormPage5.razor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using BlazorMonaco.Editor;
using System.Diagnostics.CodeAnalysis;

namespace PanoramicData.Blazor.Demo.Pages;

public partial class PDFormPage5
{
private readonly DelegatedDataProvider<DatabaseQueryModel> _dataProvider = new()
{
UpdateAsync = (model, delta, cancellationToken) =>
{
return Task.FromResult(new OperationResponse { Success = true });

}
};

private readonly DatabaseQueryModel _model = new DatabaseQueryModel
{
SqlQuery = "SELECT * \r\n FROM [Customers]\r\n WHERE [Type] = 123"
};

[AllowNull]
private PDForm<DatabaseQueryModel> _queryForm;
private FieldStringOptions QueryEditorOptions
{
get
{
return new FieldStringOptions
{
CssClass = "h-300",
Editor = FieldStringOptions.Editors.Monaco,
MonacoOptions = (_) => new StandaloneEditorConstructionOptions
{
AutomaticLayout = true,
Language = "sql"
}
};
}
}

public PDFormPage5()
{
}

private async Task OnBeginEditAsync()
{
await _queryForm.EditItemAsync(_model, FormModes.Edit);
}


private async Task OnFooterClick(string key)
{
if (_queryForm != null)
{
if (key == "Save")
{
}
await _queryForm.EditItemAsync(null, FormModes.ReadOnly).ConfigureAwait(true);
}
}
}
Empty file.
2 changes: 1 addition & 1 deletion PanoramicData.Blazor.Demo/PanoramicData.Blazor.Demo.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@


<ItemGroup>
<PackageReference Include="BlazorMonaco" Version="3.1.0" />
<PackageReference Include="BlazorMonaco" Version="3.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Components" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="8.0.0" />
</ItemGroup>
Expand Down
15 changes: 3 additions & 12 deletions PanoramicData.Blazor.Demo/Shared/DemoSourceView.razor
Original file line number Diff line number Diff line change
@@ -1,21 +1,12 @@
<style>
.pd-editor {
/*min-height: calc(100vh - 250px);*/
}
.monaco-editor-container {
height: 500px;
border: 1px solid gray;
}
</style>
<ul class="nav nav-pills p-2">
<ul class="nav nav-pills p-2">
<li class="nav-item @(ActiveTab == "Demo" ? "" : "pd-pointer")" @onclick="@(() => OnChangeTab("Demo"))">
<span class="nav-link @(ActiveTab == "Demo" ? "active" : "")">Demo</span>
</li>
<li class="nav-item @(ActiveTab == "Source" ? "" : "pd-pointer")" @onclick="@(() => OnChangeTab("Source"))">
<span class="nav-link @(ActiveTab == "Source" ? "active" : "")">Source</span>
</li>
</ul>

<div class="demo-source-view">
@if (ActiveTab == "Demo")
{
Expand All @@ -36,7 +27,7 @@
</ul>
<StandaloneCodeEditor @ref="Editor"
Id="pd-source-code"
CssClass="pd-editor"
CssClass="pd-editor h-500"
ConstructionOptions="EditorConstructionOptions" />
</div>
}
Expand Down
5 changes: 5 additions & 0 deletions PanoramicData.Blazor.Demo/Shared/NavMenu.razor
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@
<span class="fas fa-fw fa-file-alt me-2" aria-hidden="true"></span> PDForm 4
</PDNavLink>
</li>
<li class="nav-item px-3">
<PDNavLink class="nav-link" href="pdform5">
<span class="fas fa-fw fa-file-alt me-2" aria-hidden="true"></span> PDForm 5
</PDNavLink>
</li>
<li class="nav-item px-3">
<PDNavLink class="nav-link" href="pdgloballistener">
<span class="fas fa-fw fa-headphones me-2" aria-hidden="true"></span> PDGlobalListener
Expand Down
4 changes: 2 additions & 2 deletions PanoramicData.Blazor/GlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
global using Microsoft.AspNetCore.Components;
global using BlazorMonaco.Editor;
global using Microsoft.AspNetCore.Components;
global using Microsoft.AspNetCore.Components.Routing;
global using Microsoft.AspNetCore.Components.Web;
global using Microsoft.AspNetCore.WebUtilities;
Expand All @@ -25,7 +26,6 @@
global using System.Linq.Dynamic.Core;
global using System.Linq.Expressions;
global using System.Reflection;
global using System.Runtime.Serialization;
global using System.Text;
global using System.Text.RegularExpressions;
global using System.Threading;
Expand Down
26 changes: 26 additions & 0 deletions PanoramicData.Blazor/Models/FieldDisplayOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,29 @@ public record FieldDateTimeOptions : FieldDisplayOptions

public int TimeStepSecs { get; init; } = 1;
}

public record FieldStringOptions : FieldDisplayOptions
{
public enum Editors
{
TextBox,
TextArea,
Monaco
}

public FieldStringOptions()
{
CssClass = "h-100";
}

public string CodeLanguage { get; init; } = string.Empty;

public Editors Editor { get; init; }

public bool Resize { get; init; }

public int Rows { get; init; } = 4;

public Func<StandaloneCodeEditor, StandaloneEditorConstructionOptions> MonacoOptions { get; init; } = (_)
=> new StandaloneEditorConstructionOptions { ReadOnly = true };
}
62 changes: 48 additions & 14 deletions PanoramicData.Blazor/PDFormFieldEditor.razor
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,15 @@
@{
var fieldType = Field.GetFieldType();
}
<div class="editor">
<div class="editor @(Form?.Mode == FormModes.ReadOnly ? "readonly" : "")">

@if(Field.GetFieldIsNullable() && Field.DisplayOptions?.AllowNulls == true)
{
@* <input @attributes ="GetNullEditorAttributes()"
@oninput="OnHasNullValueChanged"
type="checkbox" /> *@
<PDFormCheckBox CssClass="ms-nullable"
Value="_hasValue"
ValueChanged="OnHasNullValueChanged"/>
}


@if (Field.EditTemplate != null)
{
@Field.EditTemplate(Form?.Item)
Expand Down Expand Up @@ -129,15 +125,53 @@
}
else if (fieldType?.FullName == "System.String")
{
<PDTextBox CssClass="@GetEditorClass(Field)"
AutoComplete="@Field.AutoComplete"
Blur="() => Field.SuppressErrors = false"
ShowClearButton="false"
Placeholder="@Field.Label"
IsEnabled="!IsReadOnly(Field)"
Value="@(Form?.GetFieldStringValue(Field))"
ValueChanged="(x) => Form?.SetFieldValueAsync(Field, x) ?? Task.CompletedTask"
DebounceWait="DebounceWait" />
if(Field.DisplayOptions is FieldStringOptions fso && fso.Editor != FieldStringOptions.Editors.TextBox)
{
if(fso.Editor == FieldStringOptions.Editors.TextArea)
{
<PDTextArea IsEnabled="@(!IsReadOnly(Field))"
Blur="() => Field.SuppressErrors = false"
CssClass="@($"form-control {GetEditorClass(Field)} {(fso.Resize ? "" : "no-resize")}")"
Rows="@fso.Rows"
MaxLength="@(Field.MaxLength ?? -1)"
Value="@(Form?.GetFieldStringValue(Field))"
ValueChanged="(x) => Form?.SetFieldValueAsync(Field, x) ?? Task.CompletedTask"
DebounceWait="DebounceWait" />
}
else if(fso.Editor == FieldStringOptions.Editors.Monaco)
{
@* to toggle read-only we need to destroy and re-create entire editor *@
@if(Form?.Mode == FormModes.ReadOnly)
{
<StandaloneCodeEditor @ref="_monacoEditor"
Id="my-editor"
OnDidInit="OnMonacoInitAsync"
CssClass="@($"w-100 {fso.CssClass}")"
ConstructionOptions="(ed) => PDFormFieldEditor<TItem>.GetMonacoOptionsReadOnly(fso, ed)" />
}
else
{
<StandaloneCodeEditor @ref="_monacoEditor"
Id="my-editor"
OnDidInit="OnMonacoInitAsync"
OnDidBlurEditorText="OnMonacoEditorBlurAsync"
CssClass="@($"w-100 {fso.CssClass}")"
ConstructionOptions="fso.MonacoOptions" />
}
}
}
else
{
<PDTextBox CssClass="@GetEditorClass(Field)"
AutoComplete="@Field.AutoComplete"
Blur="() => Field.SuppressErrors = false"
ShowClearButton="false"
Placeholder="@Field.Label"
IsEnabled="!IsReadOnly(Field)"
Value="@(Form?.GetFieldStringValue(Field))"
ValueChanged="(x) => Form?.SetFieldValueAsync(Field, x) ?? Task.CompletedTask"
DebounceWait="DebounceWait" />
}
}
else if (fieldType?.FullName == "System.Guid")
{
Expand Down
29 changes: 28 additions & 1 deletion PanoramicData.Blazor/PDFormFieldEditor.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
public partial class PDFormFieldEditor<TItem> where TItem : class
{
private bool _hasValue = true;
private StandaloneCodeEditor? _monacoEditor;

[Parameter]
public int DebounceWait { get; set; }
Expand Down Expand Up @@ -58,6 +59,13 @@ private OptionInfo[] GetEnumValues(FormField<TItem> field)
return options.ToArray();
}

private static StandaloneEditorConstructionOptions GetMonacoOptionsReadOnly(FieldStringOptions fso, StandaloneCodeEditor editor)
{
var opt = fso.MonacoOptions(editor);
opt.ReadOnly = true;
return opt;
}

private static Dictionary<string, object> GetNumericAttributes(FormField<TItem> field)
{
var dict = new Dictionary<string, object>();
Expand Down Expand Up @@ -119,6 +127,26 @@ private async Task OnHasNullValueChanged(bool hasValue)
}
}

private async Task OnMonacoEditorBlurAsync()
{
if (_monacoEditor != null && Form != null && Field != null)
{
var model = await _monacoEditor.GetModel();
var value = await model.GetValue(EndOfLinePreference.CRLF, true);
await Form.SetFieldValueAsync(Field, value);
}
}

private async Task OnMonacoInitAsync()
{
if (_monacoEditor != null && Form != null)
{
var model = await _monacoEditor.GetModel();
var value = Form.GetFieldStringValue(Field);
await model.SetValue(value);
}
}

public async Task OnSelectInputChanged(ChangeEventArgs args, FormField<TItem> field)
{
if (Form != null && args.Value != null)
Expand Down Expand Up @@ -190,5 +218,4 @@ private async Task UpdateValueViaCastAsync(ChangeEventArgs args, FormField<TItem
{
}
}

}
Loading

0 comments on commit 7170b72

Please sign in to comment.