12 changed files with 347 additions and 0 deletions
@ -0,0 +1,18 @@ |
|||
@inject ILocalizer Localizer |
|||
@inherits StudioComponentBase |
|||
|
|||
<MudDialog> |
|||
<DialogContent> |
|||
<EditForm EditContext="_editContext" OnValidSubmit="OnValidSubmit"> |
|||
<FluentValidationValidator @ref="_fluentValidationValidator" Validator="_validator" DisableAssemblyScanning="true" /> |
|||
<MudStack> |
|||
<MudTextField Label="@Localizer["Key"]" ReadOnly="_isEdit" @bind-Value="_model.Key" For="@(() => _model.Key)" HelperText="@Localizer["The key of the property."]" Variant="Variant.Outlined" Margin="Margin.Dense" /> |
|||
<MudTextField Label="@Localizer["Value"]" @bind-Value="_model.Value" For="@(() => _model.Value)" HelperText="@Localizer["The value of the property."]" Variant="Variant.Outlined" Margin="Margin.Dense" /> |
|||
</MudStack> |
|||
</EditForm> |
|||
</DialogContent> |
|||
<DialogActions> |
|||
<MudButton OnClick="OnCancelClicked">@Localizer["Cancel"]</MudButton> |
|||
<MudButton Color="Color.Primary" OnClick="OnSubmitClicked">@Localizer["Ok"]</MudButton> |
|||
</DialogActions> |
|||
</MudDialog> |
|||
@ -0,0 +1,80 @@ |
|||
using Blazored.FluentValidation; |
|||
using Elsa.Api.Client.Resources.WorkflowDefinitions.Models; |
|||
using Microsoft.AspNetCore.Components; |
|||
using Microsoft.AspNetCore.Components.Forms; |
|||
using MudBlazor; |
|||
|
|||
namespace LINGYUN.Abp.ElsaNext.Studio.Blazor.Components.WorkflowProperties.Tabs.Properties.Sections.Properties; |
|||
|
|||
public partial class EditPropertyDialog |
|||
{ |
|||
private bool _isEdit = false; |
|||
private readonly PropertyModel _model = new(); |
|||
private EditContext _editContext = null!; |
|||
private PropertyModelValidator _validator = null!; |
|||
private FluentValidationValidator _fluentValidationValidator = null!; |
|||
|
|||
[Parameter] public WorkflowDefinition WorkflowDefinition { get; set; } = null!; |
|||
[Parameter] public PropertyModel? Property { get; set; } |
|||
[CascadingParameter] private IMudDialogInstance MudDialog { get; set; } = null!; |
|||
|
|||
protected override async Task OnParametersSetAsync() |
|||
{ |
|||
_editContext = new(_model); |
|||
_validator = new(WorkflowDefinition, Localizer); |
|||
|
|||
if (Property == null) |
|||
{ |
|||
_model.Key = GetNewPropertyKey(WorkflowDefinition.CustomProperties); |
|||
_isEdit = false; |
|||
} |
|||
else |
|||
{ |
|||
_model.Key = Property.Key; |
|||
_model.Value = Property.Value; |
|||
_isEdit = true; |
|||
} |
|||
} |
|||
|
|||
private string GetNewPropertyKey(IDictionary<string, object> existingPropertites) |
|||
{ |
|||
var count = 0; |
|||
|
|||
while (true) |
|||
{ |
|||
var key = $"Property{++count}"; |
|||
|
|||
if (existingPropertites.All(x => x.Key != key)) |
|||
{ |
|||
return key; |
|||
} |
|||
} |
|||
} |
|||
|
|||
private Task OnCancelClicked() |
|||
{ |
|||
MudDialog.Cancel(); |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
private async Task OnSubmitClicked() |
|||
{ |
|||
if (!await _fluentValidationValidator.ValidateAsync()) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await OnValidSubmit(); |
|||
} |
|||
|
|||
private Task OnValidSubmit() |
|||
{ |
|||
var property = Property ?? new PropertyModel(); |
|||
|
|||
property.Key = _model.Key; |
|||
property.Value = _model.Value; |
|||
|
|||
MudDialog.Close(property); |
|||
return Task.CompletedTask; |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
namespace LINGYUN.Abp.ElsaNext.Studio.Blazor.Components.WorkflowProperties.Tabs.Properties.Sections.Properties; |
|||
|
|||
public class PropertyModel |
|||
{ |
|||
public string Key { get; set; } = null!; |
|||
public string Value { get; set; } = null!; |
|||
public PropertyModel() |
|||
{ |
|||
|
|||
} |
|||
|
|||
public PropertyModel(string key, string value) |
|||
{ |
|||
Key = key; |
|||
Value = value; |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
using Elsa.Api.Client.Resources.WorkflowDefinitions.Models; |
|||
using Elsa.Studio.Localization; |
|||
using FluentValidation; |
|||
|
|||
namespace LINGYUN.Abp.ElsaNext.Studio.Blazor.Components.WorkflowProperties.Tabs.Properties.Sections.Properties; |
|||
|
|||
public class PropertyModelValidator : AbstractValidator<PropertyModel> |
|||
{ |
|||
public PropertyModelValidator(WorkflowDefinition workflowDefinition, ILocalizer localizer) |
|||
{ |
|||
RuleFor(x => x.Key).NotEmpty().WithMessage(localizer["Please enter a key for the property."]); |
|||
|
|||
RuleFor(x => x.Value) |
|||
.Must((context, name, cancellationToken) => |
|||
{ |
|||
var existingKey = workflowDefinition.CustomProperties.Where(x => x.Key == name).Select(x => x.Key).FirstOrDefault(); |
|||
return existingKey == null || existingKey == context.Key; |
|||
}) |
|||
.WithMessage(localizer["A property with this key already exists in the current scope."]); |
|||
} |
|||
} |
|||
@ -0,0 +1,52 @@ |
|||
@inject ILocalizer Localizer |
|||
@inherits StudioComponentBase |
|||
|
|||
<VerticalWell ExtraPadding="40"> |
|||
<MudText Typo="Typo.overline">@Localizer["Propertites"]</MudText> |
|||
<MudStack> |
|||
<MudButton StartIcon="@Icons.Material.Outlined.Add" |
|||
Variant="Variant.Filled" |
|||
Color="Color.Primary" |
|||
Class="align-self-end" |
|||
OnClick="OnAddPropertyClicked" |
|||
Disabled="IsReadOnly"> |
|||
@Localizer["Add property"] |
|||
</MudButton> |
|||
|
|||
@if (!Properties.Any()) |
|||
{ |
|||
<MudAlert Severity="Severity.Normal" Variant="Variant.Text" Icon="@Icons.Material.Outlined.Info"> @Localizer["There are currently no propertites defined."]</MudAlert> |
|||
} |
|||
else |
|||
{ |
|||
<VerticalWell ExtraPadding="160"> |
|||
<MudSimpleTable Dense="true" Bordered="false" Striped="false" Elevation="0" Outlined="true" FixedHeader="true"> |
|||
<thead> |
|||
<tr> |
|||
<th>@Localizer["Key"]</th> |
|||
<th>@Localizer["Value"]</th> |
|||
<th></th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
|
|||
@foreach (var property in Properties) |
|||
{ |
|||
<tr> |
|||
<td>@property.Key</td> |
|||
<td>@property.Value</td> |
|||
<td style="text-align: right;"> |
|||
<MudMenu Icon="@Icons.Material.Filled.MoreVert" Size="Size.Small" Dense="true" Disabled="IsReadOnly"> |
|||
<MudMenuItem Icon="@Icons.Material.Outlined.Edit" OnClick="@(() => OnEditClicked(property))">@Localizer["Edit"]</MudMenuItem> |
|||
<MudMenuItem Icon="@Icons.Material.Outlined.Delete" OnClick="@(() => OnDeleteClicked(property))">@Localizer["Delete"]</MudMenuItem> |
|||
</MudMenu> |
|||
</td> |
|||
</tr> |
|||
} |
|||
</tbody> |
|||
</MudSimpleTable> |
|||
</VerticalWell> |
|||
} |
|||
</MudStack> |
|||
</VerticalWell> |
|||
<MudDivider /> |
|||
@ -0,0 +1,95 @@ |
|||
using Elsa.Api.Client.Resources.WorkflowDefinitions.Models; |
|||
using Elsa.Studio.Workflows.UI.Contracts; |
|||
using Microsoft.AspNetCore.Components; |
|||
using MudBlazor; |
|||
|
|||
namespace LINGYUN.Abp.ElsaNext.Studio.Blazor.Components.WorkflowProperties.Tabs.Properties.Sections.Properties; |
|||
|
|||
public partial class WorkflowDefinitionPropertitesEditor |
|||
{ |
|||
[Parameter] |
|||
public WorkflowDefinition WorkflowDefinition { get; set; } = default!; |
|||
|
|||
[Parameter] |
|||
public EventCallback WorkflowDefinitionUpdated { get; set; } |
|||
|
|||
[CascadingParameter] public IWorkspace? Workspace { get; set; } |
|||
|
|||
[Inject] IDialogService DialogService { get; set; } = default!; |
|||
|
|||
private bool IsReadOnly => Workspace?.IsReadOnly ?? true; |
|||
private ICollection<PropertyModel> Properties => WorkflowDefinition.CustomProperties |
|||
.Select(x => new PropertyModel(x.Key, x.Value.ToString()!)) |
|||
.ToList(); |
|||
|
|||
private async Task RaiseWorkflowDefinitionUpdatedAsync() |
|||
{ |
|||
if (WorkflowDefinitionUpdated.HasDelegate) |
|||
{ |
|||
await InvokeAsync(WorkflowDefinitionUpdated.InvokeAsync); |
|||
} |
|||
} |
|||
|
|||
private async Task OnEditClicked(PropertyModel property) |
|||
{ |
|||
await OpenPropertyEditorDialog(property); |
|||
} |
|||
|
|||
private async Task OnDeleteClicked(PropertyModel property) |
|||
{ |
|||
var result = await DialogService.ShowMessageBoxAsync(Localizer["Delete selected property?"], Localizer["Are you sure you want to delete the selected property?"], yesText: Localizer["Delete"], cancelText: Localizer["Cancel"]); |
|||
|
|||
if (result != true) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
WorkflowDefinition.CustomProperties.RemoveAll(x => x.Key == property.Key); |
|||
|
|||
await RaiseWorkflowDefinitionUpdatedAsync(); |
|||
} |
|||
|
|||
private async Task OnAddPropertyClicked() |
|||
{ |
|||
await OpenPropertyEditorDialog(null); |
|||
} |
|||
|
|||
private async Task OpenPropertyEditorDialog(PropertyModel? property) |
|||
{ |
|||
var isNew = property == null; |
|||
|
|||
var parameters = new DialogParameters<EditPropertyDialog> |
|||
{ |
|||
[nameof(EditPropertyDialog.WorkflowDefinition)] = WorkflowDefinition |
|||
}; |
|||
|
|||
if (!isNew) |
|||
{ |
|||
parameters[nameof(EditPropertyDialog.Property)] = property; |
|||
} |
|||
|
|||
var options = new DialogOptions |
|||
{ |
|||
MaxWidth = MaxWidth.Medium, |
|||
FullWidth = true, |
|||
CloseButton = true, |
|||
CloseOnEscapeKey = true |
|||
}; |
|||
|
|||
var title = property == null ? Localizer["Create property"] : Localizer["Edit property"]; |
|||
var dialog = await DialogService.ShowAsync<EditPropertyDialog>(title, parameters, options); |
|||
var result = await dialog.Result; |
|||
|
|||
if (result?.Canceled != false) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (result.Data is PropertyModel newProperty) |
|||
{ |
|||
WorkflowDefinition.CustomProperties[newProperty.Key] = newProperty.Value; |
|||
} |
|||
|
|||
await RaiseWorkflowDefinitionUpdatedAsync(); |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
using Elsa.Studio.Contracts; |
|||
using LINGYUN.Abp.ElsaNext.Studio.Blazor.Widgets; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
|
|||
namespace LINGYUN.Abp.ElsaNext.Studio.Blazor.Extensions; |
|||
|
|||
public static class ServiceCollectionExtensions |
|||
{ |
|||
public static IServiceCollection AddAbpElsaStudioModule(this IServiceCollection services) |
|||
{ |
|||
services.AddScoped<IWidget, WorkflowDefinitionPropertitesEditorWidget>(); |
|||
|
|||
return services; |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
using Elsa.Studio.Workflows.Widgets; |
|||
using LINGYUN.Abp.ElsaNext.Studio.Blazor.Components.WorkflowProperties.Tabs.Properties.Sections.Properties; |
|||
using Microsoft.AspNetCore.Components; |
|||
|
|||
namespace LINGYUN.Abp.ElsaNext.Studio.Blazor.Widgets; |
|||
|
|||
public class WorkflowDefinitionPropertitesEditorWidget : WorkflowDefinitionPropertiesWidgetBase |
|||
{ |
|||
public override double Order => 15; |
|||
|
|||
public override Func<IDictionary<string, object?>, RenderFragment> Render => attributes => builder => |
|||
{ |
|||
builder.OpenComponent<WorkflowDefinitionPropertitesEditor>(0); |
|||
builder.AddAttribute(1, nameof(WorkflowDefinitionPropertitesEditor.WorkflowDefinition), attributes["WorkflowDefinition"]); |
|||
builder.AddAttribute(2, nameof(WorkflowDefinitionPropertitesEditor.WorkflowDefinitionUpdated), attributes["WorkflowDefinitionUpdated"]); |
|||
builder.CloseComponent(); |
|||
|
|||
}; |
|||
} |
|||
Loading…
Reference in new issue