Skip to content

Commit

Permalink
feat(LookupService): add LookupServiceData parameter (#2988)
Browse files Browse the repository at this point in the history
* feat: 增加 LookupServiceData 属性

* feat: 增加 LookupServiceData 参数

* feat: 增加 LookupServiceBase 基类

* refactor: 增加 LookupServiceData 参数逻辑

* doc: 更新文档

* test: 更新单元测试

* chore: bump version 8.2.5-beta01

* test: 移除 MockTableColumn 类
  • Loading branch information
ArgoZhang authored Feb 23, 2024
1 parent 103d95f commit e707027
Show file tree
Hide file tree
Showing 30 changed files with 145 additions and 187 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,15 @@ private void OnClick()
{
Name = nameof(IEditorItem.LookupServiceKey),
Description = Localizer["LookupServiceKeyAttr"],
Type = "string",
Type = "string?",
ValueList = " — ",
DefaultValue = " — "
},
new()
{
Name = nameof(IEditorItem.LookupServiceData),
Description = Localizer["LookupServiceDataAttr"],
Type = "object?",
ValueList = " — ",
DefaultValue = " — "
},
Expand Down
1 change: 1 addition & 0 deletions src/BootstrapBlazor.Server/Locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -4810,6 +4810,7 @@
"LookupAttr": "Dictionary Data Source",
"LookupStringComparisonAttr": "Dictionary Data Source Comparison Rules",
"LookupServiceKeyAttr": "The LookupService service gets the Lookup data collection key value",
"LookupServiceDataAttr": "The LookupService service gets the Lookup data collection data value",
"ReadonlyAttr": "Is it read-only mode when editing",
"SearchTemplateColumnAttr": "Template",
"ShowTipsAttr": "Show cell Tooltips",
Expand Down
1 change: 1 addition & 0 deletions src/BootstrapBlazor.Server/Locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -4810,6 +4810,7 @@
"LookupAttr": "字典数据源",
"LookupStringComparisonAttr": "字典数据源比较规则",
"LookupServiceKeyAttr": "LookupService 服务获取 Lookup 数据集合键值",
"LookupServiceDataAttr": "LookupService 服务获取 Lookup 数据集合自定义数据",
"ReadonlyAttr": "编辑时是否只读模式",
"SearchTemplateColumnAttr": "模板",
"ShowTipsAttr": "显示单元格 Tooltips",
Expand Down
8 changes: 3 additions & 5 deletions src/BootstrapBlazor.Server/Services/DemoLookupService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,11 @@ namespace Microsoft.Extensions.DependencyInjection;
/// <summary>
/// 演示网站示例数据注入服务实现类
/// </summary>
internal class DemoLookupService : ILookupService
internal class DemoLookupService(IServiceProvider provider) : LookupServiceBase
{
private IServiceProvider Provider { get; }
private IServiceProvider Provider { get; } = provider;

public DemoLookupService(IServiceProvider provider) => Provider = provider;

public IEnumerable<SelectedItem>? GetItemsByKey(string? key)
public override IEnumerable<SelectedItem>? GetItemsByKey(string? key, object? data)
{
IEnumerable<SelectedItem>? items = null;
if (key == "Foo.Complete")
Expand Down
9 changes: 7 additions & 2 deletions src/BootstrapBlazor/Attributes/AutoGenerateColumnAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -198,15 +198,20 @@ public class AutoGenerateColumnAttribute : AutoGenerateBaseAttribute, ITableColu
public bool IsPopover { get; set; }

/// <summary>
/// 获得/设置 字典数据源字符串比较规则 默认 StringComparison.OrdinalIgnoreCase 大小写不敏感
/// <inheritdoc/>>
/// </summary>
public StringComparison LookupStringComparison { get; set; } = StringComparison.OrdinalIgnoreCase;

/// <summary>
/// 获得/设置 LookupService 服务指定数据集合键值 常用于外键自动转换为名称操作
/// <inheritdoc/>>
/// </summary>
public string? LookupServiceKey { get; set; }

/// <summary>
/// <inheritdoc/>>
/// </summary>
public object? LookupServiceData { get; set; }

/// <summary>
/// 获得/设置 单元格回调方法
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/BootstrapBlazor/BootstrapBlazor.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<Version>8.2.4</Version>
<Version>8.2.5-beta01</Version>
</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
Expand Down
10 changes: 8 additions & 2 deletions src/BootstrapBlazor/Components/Display/Display.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,17 @@ public partial class Display<TValue>
public IEnumerable<SelectedItem>? Lookup { get; set; }

/// <summary>
/// 获得/设置 LookupService 服务获取 Lookup 数据集合键值 常用于外键自动转换为名称操作
/// 获得/设置 <see cref="ILookupService"/> 服务获取 Lookup 数据集合键值 常用于外键自动转换为名称操作,可以通过 <see cref="LookupServiceData"/> 传递自定义数据
/// </summary>
[Parameter]
public string? LookupServiceKey { get; set; }

/// <summary>
/// 获得/设置 <see cref="ILookupService"/> 服务获取 Lookup 数据集合键值自定义数据,通过 <see cref="LookupServiceKey"/> 指定键值
/// </summary>
[Parameter]
public object? LookupServiceData { get; set; }

[Inject]
[NotNull]
private ILookupService? LookupService { get; set; }
Expand Down Expand Up @@ -74,7 +80,7 @@ public override Task SetParametersAsync(ParameterView parameters)

if (!string.IsNullOrEmpty(LookupServiceKey))
{
Lookup = LookupService.GetItemsByKey(LookupServiceKey);
Lookup = LookupService.GetItemsByKey(LookupServiceKey, LookupServiceData);
}

// For derived components, retain the usual lifecycle with OnInit/OnParametersSet/etc.
Expand Down
8 changes: 7 additions & 1 deletion src/BootstrapBlazor/Components/EditorForm/EditorItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,11 +173,17 @@ public class EditorItem<TValue> : ComponentBase, IEditorItem
public StringComparison LookupStringComparison { get; set; } = StringComparison.OrdinalIgnoreCase;

/// <summary>
/// 获得/设置 LookupService 服务获取 Lookup 数据集合键值 常用于外键自动转换为名称操作
/// <inheritdoc/>>
/// </summary>
[Parameter]
public string? LookupServiceKey { get; set; }

/// <summary>
/// <inheritdoc/>>
/// </summary>
[Parameter]
public object? LookupServiceData { get; set; }

/// <summary>
/// 获得/设置 自定义验证集合
/// </summary>
Expand Down
11 changes: 8 additions & 3 deletions src/BootstrapBlazor/Components/EditorForm/IEditorItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace BootstrapBlazor.Components;

/// <summary>
///
/// IEditorItem 接口
/// </summary>
public interface IEditorItem
{
Expand Down Expand Up @@ -101,15 +101,20 @@ public interface IEditorItem
bool IsPopover { get; set; }

/// <summary>
/// 获得/设置 字典数据源字符串比较规则 默认 StringComparison.OrdinalIgnoreCase 大小写不敏感
/// 获得/设置 字典数据源字符串比较规则 默认 <see cref="StringComparison.OrdinalIgnoreCase" /> 大小写不敏感
/// </summary>
StringComparison LookupStringComparison { get; set; }

/// <summary>
/// 获得/设置 LookupService 服务获取 Lookup 数据集合键值 常用于外键自动转换为名称操作
/// 获得/设置 <see cref="ILookupService"/> 服务获取 Lookup 数据集合键值 常用于外键自动转换为名称操作,可以通过 <see cref="LookupServiceData"/> 传递自定义数据
/// </summary>
string? LookupServiceKey { get; set; }

/// <summary>
/// 获得/设置 <see cref="ILookupService"/> 服务获取 Lookup 数据集合键值自定义数据,通过 <see cref="LookupServiceKey"/> 指定键值
/// </summary>
object? LookupServiceData { get; set; }

/// <summary>
/// 获得/设置 自定义验证集合
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ protected override void OnInitialized()
FieldKey = Column.GetFieldName();
Column.Filter = this;

_lookup = new(() => Column.Lookup ?? LookupService.GetItemsByKey(Column.LookupServiceKey));
_lookup = new(() => Column.Lookup ?? LookupService.GetItemsByKey(Column.LookupServiceKey, Column.LookupServiceData));
_step = Column.Step;
}

Expand Down
9 changes: 7 additions & 2 deletions src/BootstrapBlazor/Components/Table/InternalTableColumn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,15 +135,20 @@ class InternalTableColumn(string fieldName, Type fieldType, string? fieldText =
public bool IsPopover { get; set; }

/// <summary>
/// 获得/设置 字典数据源字符串比较规则 默认 StringComparison.OrdinalIgnoreCase 大小写不敏感
/// <inheritdoc/>>
/// </summary>
public StringComparison LookupStringComparison { get; set; } = StringComparison.OrdinalIgnoreCase;

/// <summary>
/// 获得/设置 LookupService 服务获取 Lookup 数据集合键值 常用于外键自动转换为名称操作
/// <inheritdoc/>>
/// </summary>
public string? LookupServiceKey { get; set; }

/// <summary>
/// <inheritdoc/>>
/// </summary>
public object? LookupServiceData { get; set; }

/// <summary>
/// 获得/设置 单元格回调方法
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/BootstrapBlazor/Components/Table/Table.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1049,7 +1049,7 @@ protected RenderFragment GetValue(ITableColumn col, TItem item) => builder =>
{
// 未设置 Lookup
// 设置 LookupService 键值
col.Lookup = LookupService.GetItemsByKey(col.LookupServiceKey);
col.Lookup = LookupService.GetItemsByKey(col.LookupServiceKey, col.LookupServiceData);
}
builder.AddContent(20, col.RenderValue(item));
}
Expand Down
10 changes: 8 additions & 2 deletions src/BootstrapBlazor/Components/Table/TableColumn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -382,17 +382,23 @@ public class TableColumn<TItem, TType> : BootstrapComponentBase, ITableColumn
public bool IsPopover { get; set; }

/// <summary>
/// 获得/设置 字典数据源字符串比较规则 默认 StringComparison.OrdinalIgnoreCase 大小写不敏感
/// <inheritdoc/>>
/// </summary>
[Parameter]
public StringComparison LookupStringComparison { get; set; } = StringComparison.OrdinalIgnoreCase;

/// <summary>
/// 获得/设置 字典数据源服务的类别 常用于外键自动转换为名称操作
/// <inheritdoc/>>
/// </summary>
[Parameter]
public string? LookupServiceKey { get; set; }

/// <summary>
/// <inheritdoc/>>
/// </summary>
[Parameter]
public object? LookupServiceData { get; set; }

/// <summary>
/// 获得/设置 单元格回调方法
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions src/BootstrapBlazor/Extensions/ITableColumnExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public static void CopyValue(this ITableColumn dest, IEditorItem source)
if (source.IsPopover) dest.IsPopover = source.IsPopover;
if (source.LookupStringComparison != StringComparison.OrdinalIgnoreCase) dest.LookupStringComparison = source.LookupStringComparison;
if (source.LookupServiceKey != null) dest.LookupServiceKey = source.LookupServiceKey;
if (source.LookupServiceData != null) dest.LookupServiceData = source.LookupServiceData;
if (source.IsReadonlyWhenAdd) dest.IsReadonlyWhenAdd = source.IsReadonlyWhenAdd;
if (source.IsReadonlyWhenEdit) dest.IsReadonlyWhenEdit = source.IsReadonlyWhenEdit;
if (source.Readonly) dest.Readonly = source.Readonly;
Expand Down
7 changes: 7 additions & 0 deletions src/BootstrapBlazor/Services/ILookupService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,11 @@ public interface ILookupService
/// </summary>
/// <param name="key">获得 Lookup 数据集合键值</param>
IEnumerable<SelectedItem>? GetItemsByKey(string? key);

/// <summary>
/// 根据指定键值获取 Lookup 集合方法
/// </summary>
/// <param name="key">获得 Lookup 数据集合键值</param>
/// <param name="data">Lookup 键值附加数据</param>
IEnumerable<SelectedItem>? GetItemsByKey(string? key, object? data);
}
21 changes: 21 additions & 0 deletions src/BootstrapBlazor/Services/LookupServiceBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/

namespace BootstrapBlazor.Components;

/// <summary>
/// LookupService 基类
/// </summary>
public abstract class LookupServiceBase : ILookupService
{
/// <summary>
///<inheritdoc/>
/// </summary>
public virtual IEnumerable<SelectedItem>? GetItemsByKey(string? key) => GetItemsByKey(key, null);

/// <summary>
///<inheritdoc/>
/// </summary>
public abstract IEnumerable<SelectedItem>? GetItemsByKey(string? key, object? data);
}
7 changes: 3 additions & 4 deletions src/BootstrapBlazor/Services/NullLookupService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ namespace BootstrapBlazor.Components;
/// <summary>
/// 内部默认字典服务实现类
/// </summary>
internal class NullLookupService : ILookupService
class NullLookupService : LookupServiceBase
{
/// <summary>
/// 根据指定键值获取 Lookup 集合方法
/// <inheritdoc/>>
/// </summary>
/// <param name="key">获得 Lookup 数据集合键值</param>
public IEnumerable<SelectedItem>? GetItemsByKey(string? key) => null;
public override IEnumerable<SelectedItem>? GetItemsByKey(string? key, object? data) => null;
}
13 changes: 7 additions & 6 deletions src/BootstrapBlazor/Utils/Utility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -411,20 +411,21 @@ public static void CreateDisplayByFieldType(this RenderTreeBuilder builder, IEdi
builder.AddAttribute(1, nameof(Display<string>.DisplayText), displayName);
builder.AddAttribute(2, nameof(Display<string>.Value), fieldValue);
builder.AddAttribute(3, nameof(Display<string>.LookupServiceKey), item.LookupServiceKey);
builder.AddAttribute(4, nameof(Display<string>.ShowLabelTooltip), item.ShowLabelTooltip);
builder.AddAttribute(4, nameof(Display<string>.LookupServiceData), item.LookupServiceData);
builder.AddAttribute(5, nameof(Display<string>.ShowLabelTooltip), item.ShowLabelTooltip);
if (item is ITableColumn col)
{
if (col.Formatter != null)
{
builder.AddAttribute(5, nameof(Display<string>.FormatterAsync), CacheManager.GetFormatterInvoker(fieldType, col.Formatter));
builder.AddAttribute(6, nameof(Display<string>.FormatterAsync), CacheManager.GetFormatterInvoker(fieldType, col.Formatter));
}
else if (!string.IsNullOrEmpty(col.FormatString))
{
builder.AddAttribute(5, nameof(Display<string>.FormatString), col.FormatString);
builder.AddAttribute(6, nameof(Display<string>.FormatString), col.FormatString);
}
builder.AddAttribute(6, "class", col.CssClass);
builder.AddAttribute(7, "class", col.CssClass);
}
builder.AddMultipleAttributes(7, item.ComponentParameters);
builder.AddMultipleAttributes(8, item.ComponentParameters);
builder.CloseComponent();
}
}
Expand All @@ -448,7 +449,7 @@ public static void CreateComponentByFieldType(this RenderTreeBuilder builder, Co
var fieldValue = GenerateValue(model, fieldName);
var fieldValueChanged = GenerateValueChanged(component, model, fieldName, fieldType);
var valueExpression = GenerateValueExpression(model, fieldName, fieldType);
var lookup = item.Lookup ?? lookUpService?.GetItemsByKey(item.LookupServiceKey);
var lookup = item.Lookup ?? lookUpService?.GetItemsByKey(item.LookupServiceKey, item.LookupServiceData);
var componentType = item.ComponentType ?? GenerateComponentType(fieldType, item.Rows != 0, lookup);
builder.OpenComponent(0, componentType);
if (componentType.IsSubclassOf(typeof(ValidateBase<>).MakeGenericType(fieldType)))
Expand Down
2 changes: 2 additions & 0 deletions test/UnitTest/Attributes/AutoGenerateClassTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public void AutoGenerateColumn_Ok()
Rows = 1,
LookupStringComparison = StringComparison.Ordinal,
LookupServiceKey = "test-lookup",
LookupServiceData = true,
GroupName = "Test",
GroupOrder = 1,
ShowHeaderTooltip = true,
Expand Down Expand Up @@ -89,6 +90,7 @@ public void AutoGenerateColumn_Ok()
Assert.Equal("Test", attr.GroupName);
Assert.Equal(1, attr.GroupOrder);
Assert.Equal("test-lookup", attr.LookupServiceKey);
Assert.Equal(true, attr.LookupServiceData);
Assert.True(attr.ShowHeaderTooltip);
Assert.True(attr.HeaderTextWrap);
Assert.True(attr.HeaderTextEllipsis);
Expand Down
1 change: 1 addition & 0 deletions test/UnitTest/Components/DisplayTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public void LookupService_Ok()
var cut = Context.RenderComponent<Display<List<string>>>(pb =>
{
pb.Add(a => a.LookupServiceKey, "FooLookup");
pb.Add(a => a.LookupServiceData, true);
pb.Add(a => a.Value, ["v1", "v2"]);
});
Assert.Contains("LookupService-Test-1,LookupService-Test-2", cut.Markup);
Expand Down
3 changes: 2 additions & 1 deletion test/UnitTest/Components/EditorFormTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public void Items_Ok()
Context.RenderComponent<EditorForm<Foo>>(pb =>
{
pb.Add(a => a.Model, foo);
pb.Add(a => a.Items, new List<MockTableColumn>
pb.Add(a => a.Items, new List<InternalTableColumn>
{
new("Id", typeof(int)),
new("Name", typeof(string))
Expand Down Expand Up @@ -403,6 +403,7 @@ public void LookupServiceKey_Ok()
builder.AddAttribute(index++, nameof(EditorItem<Foo, string>.FieldExpression), Utility.GenerateValueExpression(foo, nameof(Foo.Name), typeof(string)));
builder.AddAttribute(index++, nameof(EditorItem<Foo, string>.Text), "Test-Text");
builder.AddAttribute(index++, nameof(EditorItem<Foo, string>.LookupServiceKey), "FooLookup");
builder.AddAttribute(index++, nameof(EditorItem<Foo, string>.LookupServiceData), true);
builder.AddAttribute(index++, nameof(EditorItem<Foo, string>.LookupStringComparison), StringComparison.OrdinalIgnoreCase);
builder.CloseComponent();
});
Expand Down
1 change: 1 addition & 0 deletions test/UnitTest/Components/TableFilterTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ private static RenderFragment<Foo> CreateTableColumns() => foo => builder =>
builder.OpenComponent<TableColumn<Foo, int>>(index++);
builder.AddAttribute(index++, nameof(TableColumn<Foo, int>.Field), foo.Id);
builder.AddAttribute(index++, nameof(TableColumn<Foo, int>.LookupServiceKey), "FooLookup");
builder.AddAttribute(index++, nameof(TableColumn<Foo, int>.LookupServiceData), new Foo());
builder.AddAttribute(index++, nameof(TableColumn<Foo, int>.FieldExpression), foo.GenerateValueExpression(nameof(Foo.Id), typeof(int)));
builder.AddAttribute(index++, nameof(TableColumn<Foo, int>.Filterable), true);
builder.CloseComponent();
Expand Down
7 changes: 4 additions & 3 deletions test/UnitTest/Components/TableTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,7 @@ public void ResetFilter_Null()
// 利用 MockTableColumn 设置 Filter 为 null 测试内部 Filter 为空时单元测试
var table = cut.FindComponent<Table<Foo>>();
table.Instance.Columns.Clear();
table.Instance.Columns.Add(new MockTableColumn("Name", typeof(string)));
table.Instance.Columns.Add(new InternalTableColumn("Name", typeof(string)));
cut.InvokeAsync(() => table.Instance.ResetFilters());
}

Expand Down Expand Up @@ -4757,10 +4757,10 @@ public void TableColumn_Align()
});
});
var table = cut.FindComponent<MockTable>();
var css = table.Instance.TestGetCellClassString(new MockTableColumn("Name", typeof(string)) { Align = Alignment.Center });
var css = table.Instance.TestGetCellClassString(new InternalTableColumn("Name", typeof(string)) { Align = Alignment.Center });
Assert.Equal("table-cell center", css);

css = table.Instance.TestGetHeaderWrapperClassString(new MockTableColumn("Name", typeof(string)) { Align = Alignment.Center });
css = table.Instance.TestGetHeaderWrapperClassString(new InternalTableColumn("Name", typeof(string)) { Align = Alignment.Center });
Assert.Equal("table-cell center", css);
}

Expand Down Expand Up @@ -6924,6 +6924,7 @@ public async Task GetValue_LookupServiceKey()
builder.AddAttribute(1, "Field", true);
builder.AddAttribute(2, "FieldExpression", Utility.GenerateValueExpression(foo, "Complete", typeof(bool)));
builder.AddAttribute(3, "LookupServiceKey", "test");
builder.AddAttribute(4, "LookupServiceData", true);
builder.CloseComponent();
});
});
Expand Down
Loading

0 comments on commit e707027

Please sign in to comment.