Skip to content

Commit

Permalink
refactor: segregate rules grid to a separate component
Browse files Browse the repository at this point in the history
  • Loading branch information
luispfgarces committed Nov 5, 2024
1 parent 379771a commit a3666a6
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 179 deletions.
2 changes: 1 addition & 1 deletion rules-framework.sln
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rules.Framework.Rql", "src\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rules.Framework.Rql.Tests", "tests\Rules.Framework.Rql.Tests\Rules.Framework.Rql.Tests.csproj", "{776E54A7-9099-4EBD-9C62-A371DFED58E5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rules.Framework.Rql.IntegrationTests", "tests\Rules.Framework.Rql.IntegrationTests\Rules.Framework.Rql.IntegrationTests.csproj", "{C24A2234-AD6A-4377-9FAA-9CC58386107C}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rules.Framework.Rql.IntegrationTests", "tests\Rules.Framework.Rql.IntegrationTests\Rules.Framework.Rql.IntegrationTests.csproj", "{C24A2234-AD6A-4377-9FAA-9CC58386107C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@
<Accordion @ref="innerAccordion" AlwaysOpen="true">
@foreach (var conditionNode in this.ConditionNodes)
{
if (conditionNode is ComposedConditionNode composedConditionNode)
if (conditionNode is ComposedConditionNodeViewModel composedConditionNode)
{
<AccordionItem Title="@($"{composedConditionNode.LogicalOperator} {{...}}")">
<Content>
<RuleConditionHierarchicalAccordion @ref="InnerReference" ConditionNodes="composedConditionNode.ChildConditionNodes" />
</Content>
</AccordionItem>
}
else if (conditionNode is ValueConditionNode valueConditionNode)
else if (conditionNode is ValueConditionNodeViewModel valueConditionNode)
{
var shortValueConditionText = $"{valueConditionNode.Condition} {valueConditionNode.Operator} {valueConditionNode.GetOperandPrettyPrint()}";
var shortValueConditionText = $"{valueConditionNode.Condition} {valueConditionNode.Operator} {GetOperandPrettyPrint(valueConditionNode.Operand)}";
<AccordionItem Title="@shortValueConditionText">
<Content>
<div class="row">
Expand All @@ -46,7 +46,7 @@
<p><strong>Operator:</strong> <article>@(valueConditionNode.Operator)</article></p>
</div>
<div class="col-sm-3">
<p><strong>Operand:</strong> <article>@(valueConditionNode.GetOperandPrettyPrint())</article></p>
<p><strong>Operand:</strong> <article>@(GetOperandPrettyPrint(valueConditionNode.Operand))</article></p>
</div>
</div>
</CardText>
Expand All @@ -73,7 +73,7 @@
}

[Parameter]
public IEnumerable<ConditionNode> ConditionNodes { get; set; } = Enumerable.Empty<ConditionNode>();
public IEnumerable<ConditionNodeViewModel> ConditionNodes { get; set; } = Enumerable.Empty<ConditionNodeViewModel>();

[Parameter]
public bool EnableCollapseAllButton { get; set; } = false;
Expand Down Expand Up @@ -105,66 +105,45 @@
}
}

public sealed class ComposedConditionNode : ConditionNode
internal string GetOperandPrettyPrint(object operand)
{
public IEnumerable<ConditionNode> ChildConditionNodes { get; internal set; }
}

public class ConditionNode
{
public string LogicalOperator { get; internal set; }
}

public sealed class ValueConditionNode : ConditionNode
{
public string Condition { get; internal set; }

public string DataType { get; internal set; }

public dynamic Operand { get; internal set; }

public string Operator { get; internal set; }

internal string GetOperandPrettyPrint()
var operandPrettyPrintBuilder = new StringBuilder();
if (operand is IEnumerable elements && elements is not string)
{
var operandPrettyPrintBuilder = new StringBuilder();
if (this.Operand is IEnumerable elements && elements is not string)
operandPrettyPrintBuilder.Append("{ ");
var elementsProcessedCount = 0;
foreach (var element in elements)
{
operandPrettyPrintBuilder.Append("{ ");
var elementsProcessedCount = 0;
foreach (var element in elements)
if (elementsProcessedCount >= 10)
{
if (elementsProcessedCount >= 10)
{
operandPrettyPrintBuilder.Append(", ...");
}
else if (elementsProcessedCount > 0)
{
operandPrettyPrintBuilder.Append(',');
}

operandPrettyPrintBuilder.Append(element switch
{
null => "(null)",
"" => "(empty)",
_ => element,
});
elementsProcessedCount++;
operandPrettyPrintBuilder.Append(", ...");
}
else if (elementsProcessedCount > 0)
{
operandPrettyPrintBuilder.Append(',');
}

operandPrettyPrintBuilder.Append(" }");
}
else
{
operandPrettyPrintBuilder.Append(this.Operand switch
operandPrettyPrintBuilder.Append(element switch
{
null => "(null)",
"" => "(empty)",
_ => this.Operand,
_ => element,
});
elementsProcessedCount++;
}

return operandPrettyPrintBuilder.ToString();
operandPrettyPrintBuilder.Append(" }");
}
else
{
operandPrettyPrintBuilder.Append(operand switch
{
null => "(null)",
"" => "(empty)",
_ => operand,
});
}

return operandPrettyPrintBuilder.ToString();
}
}
112 changes: 112 additions & 0 deletions src/Rules.Framework.WebUI/Components/PageComponents/RulesGrid.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
@attribute [ExcludeFromCodeCoverage]
@rendermode InteractiveServer
@using System.Text.Json
@using System.Text.Json.Serialization

<div class="table-responsive">
<Grid TItem="RuleViewModel"
DataProvider="LoadRulesAsync"
AllowPaging="true"
AllowSorting="true"
AllowFiltering="true"
Responsive="true"
PageSizeSelectorVisible="true"
PageSizeSelectorItems="new[] { 5, 10, 50 }"
PageSize="@DefaultPageSize"
Class="table table-hover table-bordered table-striped"
@ref="rulesGrid"
AllowDetailView="true">
<GridColumns>
<GridColumn TItem="RuleViewModel" HeaderText="Priority" PropertyName="Priority" SortKeySelector="item => item.Priority">
@(context.Priority)
</GridColumn>
<GridColumn TItem="RuleViewModel" HeaderText="Ruleset" PropertyName="Ruleset" SortKeySelector="item => item.Ruleset">
@(context.Ruleset)
</GridColumn>
<GridColumn TItem="RuleViewModel" HeaderText="Name" PropertyName="Name" SortKeySelector="item => item.Name">
@(context.Name)
</GridColumn>
<GridColumn TItem="RuleViewModel" HeaderText="Date begin" PropertyName="DateBegin" SortKeySelector="item => item.DateBegin">
@(context.DateBegin)
</GridColumn>
<GridColumn TItem="RuleViewModel" HeaderText="Date end" PropertyName="DateEnd" SortKeySelector="item => item.DateEnd">
@(context.DateEnd)
</GridColumn>
<GridColumn TItem="RuleViewModel" HeaderText="Content" PropertyName="Content">
@(JsonSerializer.Serialize(context.Content, this.jsonSerializerOptions))
</GridColumn>
<GridColumn TItem="RuleViewModel" HeaderText="Status" PropertyName="Active">
@if (context.Active)
{
<Badge Color="BadgeColor.Primary" IndicatorType="BadgeIndicatorType.RoundedPill" Class="p-2">Active</Badge>
}
else
{
<Badge Color="BadgeColor.Secondary" IndicatorType="BadgeIndicatorType.RoundedPill" Class="p-2">Deactivated</Badge>
}
</GridColumn>
</GridColumns>
<GridDetailView TItem="RuleViewModel">
<Tabs EnableFadeEffect="true">
<Tab Title="JSON view" Active="true">
<Content>
<div class="overflow-auto" style="max-height: 40vh;">
<pre>
<code>
@(JsonSerializer.Serialize(context.RootCondition, this.jsonSerializerOptions))
</code>
</pre>
</div>
</Content>
</Tab>
<Tab Title="Tree view">
<Content>
<div class="overflow-auto" style="max-height: 40vh;">
@if (context.RootCondition is not null)
{
var conditionNodes = new[] { context.RootCondition };
<RuleConditionHierarchicalAccordion ConditionNodes="@conditionNodes"
EnableCollapseAllButton="true"
EnableShowAllButton="true" />
}
</div>
</Content>
</Tab>
</Tabs>
</GridDetailView>
</Grid>
</div>

@code {
private const int DefaultPageSize = 5;
private JsonSerializerOptions jsonSerializerOptions;
private Grid<RuleViewModel> rulesGrid;

public RulesGrid()
{
this.jsonSerializerOptions = new JsonSerializerOptions
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
IncludeFields = true,
WriteIndented = true,
};
this.jsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
this.jsonSerializerOptions.Converters.Add(new PolymorphicWriteOnlyJsonConverter<ConditionNodeViewModel>());
}

[Parameter]
public RulesGridProviderDelegate DataProvider { get; set; }

public async Task RefreshAsync()
{
await this.rulesGrid.RefreshDataAsync();
}

private async Task<GridDataProviderResult<RuleViewModel>> LoadRulesAsync(GridDataProviderRequest<RuleViewModel> request)
{
var rules = await this.DataProvider.Invoke();
return request.ApplyTo(rules);
}

public delegate Task<IEnumerable<RuleViewModel>> RulesGridProviderDelegate();
}
Loading

0 comments on commit a3666a6

Please sign in to comment.