Skip to content

Commit 625f6c9

Browse files
authored
Merge pull request #4 from Parziwal/feature/aspnetcore-blazor
Common blazor components
2 parents ac16086 + 5c6c839 commit 625f6c9

File tree

88 files changed

+3550
-5
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+3550
-5
lines changed

AutSoftCore.sln

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{4E394277
3232
README.md = README.md
3333
EndProjectSection
3434
EndProject
35-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutSoft.AspNetCore.Auth", "src\AutSoft.AspNetCore.Auth\AutSoft.AspNetCore.Auth.csproj", "{6B158B44-E28E-4276-BB65-72CDA4163F39}"
35+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutSoft.AspNetCore.Auth", "src\AutSoft.AspNetCore.Auth\AutSoft.AspNetCore.Auth.csproj", "{6B158B44-E28E-4276-BB65-72CDA4163F39}"
36+
EndProject
37+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutSoft.AspNetCore.Blazor", "src\AutSoft.AspNetCore.Blazor\AutSoft.AspNetCore.Blazor.csproj", "{1E00D30A-1EF0-4DAD-98C9-61FEE3EA7EF6}"
38+
EndProject
39+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutSoft.Mud.Blazor", "src\AutSoft.Mud.Blazor\AutSoft.Mud.Blazor.csproj", "{91EDCF80-45C8-4728-9240-52DA8DAD8F02}"
3640
EndProject
3741
Global
3842
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -68,6 +72,14 @@ Global
6872
{6B158B44-E28E-4276-BB65-72CDA4163F39}.Debug|Any CPU.Build.0 = Debug|Any CPU
6973
{6B158B44-E28E-4276-BB65-72CDA4163F39}.Release|Any CPU.ActiveCfg = Release|Any CPU
7074
{6B158B44-E28E-4276-BB65-72CDA4163F39}.Release|Any CPU.Build.0 = Release|Any CPU
75+
{1E00D30A-1EF0-4DAD-98C9-61FEE3EA7EF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
76+
{1E00D30A-1EF0-4DAD-98C9-61FEE3EA7EF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
77+
{1E00D30A-1EF0-4DAD-98C9-61FEE3EA7EF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
78+
{1E00D30A-1EF0-4DAD-98C9-61FEE3EA7EF6}.Release|Any CPU.Build.0 = Release|Any CPU
79+
{91EDCF80-45C8-4728-9240-52DA8DAD8F02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
80+
{91EDCF80-45C8-4728-9240-52DA8DAD8F02}.Debug|Any CPU.Build.0 = Debug|Any CPU
81+
{91EDCF80-45C8-4728-9240-52DA8DAD8F02}.Release|Any CPU.ActiveCfg = Release|Any CPU
82+
{91EDCF80-45C8-4728-9240-52DA8DAD8F02}.Release|Any CPU.Build.0 = Release|Any CPU
7183
EndGlobalSection
7284
GlobalSection(SolutionProperties) = preSolution
7385
HideSolutionNode = FALSE
@@ -80,6 +92,8 @@ Global
8092
{28371EF8-D3D3-40CA-AAE9-29D80AE0BF3F} = {C46AA3F7-CBFE-428A-AA49-D1A1D40AB8A6}
8193
{D4D62897-E6D6-484E-AE4E-F3A0347ADD88} = {7029D162-AEB0-4B68-A21E-90ABCD21DAD3}
8294
{6B158B44-E28E-4276-BB65-72CDA4163F39} = {C46AA3F7-CBFE-428A-AA49-D1A1D40AB8A6}
95+
{1E00D30A-1EF0-4DAD-98C9-61FEE3EA7EF6} = {C46AA3F7-CBFE-428A-AA49-D1A1D40AB8A6}
96+
{91EDCF80-45C8-4728-9240-52DA8DAD8F02} = {C46AA3F7-CBFE-428A-AA49-D1A1D40AB8A6}
8397
EndGlobalSection
8498
GlobalSection(ExtensibilityGlobals) = postSolution
8599
SolutionGuid = {E4767DF1-41A6-4BF0-A957-2718986D8BC7}

src/AutSoft.All/AutSoft.All.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88

99
<ItemGroup>
1010
<ProjectReference Include="..\AutSoft.AspNetCore.Auth\AutSoft.AspNetCore.Auth.csproj" />
11+
<ProjectReference Include="..\AutSoft.AspNetCore.Blazor\AutSoft.AspNetCore.Blazor.csproj" />
1112
<ProjectReference Include="..\AutSoft.DbScaffolding.Identity\AutSoft.DbScaffolding.Identity.csproj" />
1213
<ProjectReference Include="..\AutSoft.Linq\AutSoft.Linq.csproj" />
14+
<ProjectReference Include="..\AutSoft.Mud.Blazor\AutSoft.Mud.Blazor.csproj" />
1315
</ItemGroup>
1416

1517
</Project>

src/AutSoft.All/ServiceCollectionExtensions.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using AutSoft.AspNetCore.Auth;
2+
using AutSoft.AspNetCore.Blazor;
23
using AutSoft.Common;
4+
using AutSoft.Mud.Blazor;
35

46
using Microsoft.Extensions.DependencyInjection;
57

@@ -18,6 +20,8 @@ public static IServiceCollection AddAutSoftAll(this IServiceCollection services)
1820
{
1921
services.AddAutSoftAspNetCoreAuth();
2022
services.AddAutSoftCommon();
23+
services.AddAutSoftAspNetCoreBlazor();
24+
services.AddAutSoftMudBlazor();
2125

2226
return services;
2327
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Razor">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net6.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<SupportedPlatform Include="browser" />
11+
</ItemGroup>
12+
13+
<ItemGroup>
14+
<PackageReference Include="FluentValidation" />
15+
<PackageReference Include="Microsoft.AspNetCore.Components.Web" />
16+
<PackageReference Include="Microsoft.TypeScript.MSBuild">
17+
<PrivateAssets>all</PrivateAssets>
18+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
19+
</PackageReference>
20+
</ItemGroup>
21+
22+
<ItemGroup>
23+
<ProjectReference Include="..\AutSoft.Core\AutSoft.Common.csproj" />
24+
<ProjectReference Include="..\AutSoft.Linq\AutSoft.Linq.csproj" />
25+
</ItemGroup>
26+
27+
<Target Name="RemoveTSConfigFileFromPackage" AfterTargets="CompileTypeScriptWithTSConfig">
28+
<ItemGroup>
29+
<Content Remove="**\tsconfig.json" />
30+
</ItemGroup>
31+
</Target>
32+
</Project>
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
namespace AutSoft.AspNetCore.Blazor.Autocomplete;
2+
3+
/// <summary>
4+
/// Autocomplete field data source.
5+
/// </summary>
6+
/// <typeparam name="TKey">Key type.</typeparam>
7+
/// <typeparam name="TItem">Item type.</typeparam>
8+
public class AutoCompleteDataSource<TKey, TItem>
9+
{
10+
private readonly Func<string, Task<IEnumerable<TItem>>> _search;
11+
private readonly Func<TItem, TKey> _keySelector;
12+
private readonly Func<TItem, string> _nameSelector;
13+
private IEnumerable<TItem>? _currentItems;
14+
15+
/// <summary>
16+
/// Constructor of the AutoCompleteDataSource.
17+
/// </summary>
18+
/// <param name="search">Search function.</param>
19+
/// <param name="keySelector">Key selector.</param>
20+
/// <param name="nameSelector">Name selector.</param>
21+
public AutoCompleteDataSource(Func<string, Task<IEnumerable<TItem>>> search, Func<TItem, TKey> keySelector, Func<TItem, string> nameSelector)
22+
{
23+
_search = search;
24+
_keySelector = keySelector;
25+
_nameSelector = nameSelector;
26+
}
27+
28+
/// <summary>
29+
/// Gets the keys of the searched items.
30+
/// </summary>
31+
/// <param name="search">Search term.</param>
32+
/// <returns>Items keys.</returns>
33+
public async Task<IEnumerable<TKey>> SearchAsync(string search)
34+
{
35+
_currentItems = await _search(search);
36+
return _currentItems.Select(i => _keySelector(i));
37+
}
38+
39+
/// <summary>
40+
/// Gets or sets the currently selected item.
41+
/// </summary>
42+
/// <param name="i">Index,</param>
43+
/// <returns>Item type.</returns>
44+
public TItem? this[TKey? key]
45+
{
46+
private get
47+
{
48+
if (_currentItems == null)
49+
return default;
50+
51+
return _currentItems.SingleOrDefault(i => EqualityComparer<TKey>.Default.Equals(key, _keySelector(i)));
52+
}
53+
set
54+
{
55+
if (EqualityComparer<TItem>.Default.Equals(value, default))
56+
{
57+
_currentItems = new List<TItem>();
58+
return;
59+
}
60+
61+
_currentItems = new List<TItem> { value! };
62+
}
63+
}
64+
65+
/// <summary>
66+
/// Gets the name of the item with the specified key.
67+
/// </summary>
68+
/// <param name="key">Key of the item.</param>
69+
/// <returns>Name of the item.</returns>
70+
public string? GetItemName(TKey? key)
71+
{
72+
if (EqualityComparer<TKey>.Default.Equals(key, default))
73+
return null;
74+
75+
var selectedItem = this[key];
76+
77+
return !EqualityComparer<TItem>.Default.Equals(selectedItem, default) ? _nameSelector(selectedItem!) : null;
78+
}
79+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using Microsoft.JSInterop;
2+
3+
namespace AutSoft.AspNetCore.Blazor.Clipboard;
4+
5+
/// <inheritdoc />
6+
public class ClipboardService : IClipboardService
7+
{
8+
private readonly IJSRuntime _jsRuntime;
9+
10+
/// <summary>
11+
/// Constructor of the ClipboardService.
12+
/// </summary>
13+
/// <param name="jsRuntime">Javascript runtime.</param>
14+
public ClipboardService(IJSRuntime jsRuntime)
15+
{
16+
_jsRuntime = jsRuntime;
17+
}
18+
19+
/// <inheritdoc />
20+
public ValueTask<string> ReadTextAsync()
21+
{
22+
return _jsRuntime.InvokeAsync<string>("navigator.clipboard.readText");
23+
}
24+
25+
/// <inheritdoc />
26+
public ValueTask WriteTextAsync(string text)
27+
{
28+
return _jsRuntime.InvokeVoidAsync("navigator.clipboard.writeText", text);
29+
}
30+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
namespace AutSoft.AspNetCore.Blazor.Clipboard;
2+
3+
/// <summary>
4+
/// Service providing access to clipboard.
5+
/// </summary>
6+
public interface IClipboardService
7+
{
8+
/// <summary>
9+
/// Read text from clipboard.
10+
/// </summary>
11+
ValueTask<string> ReadTextAsync();
12+
13+
/// <summary>
14+
/// Write text to clipboard.
15+
/// </summary>
16+
ValueTask WriteTextAsync(string text);
17+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
using Microsoft.AspNetCore.Components;
2+
3+
using System.Reflection;
4+
5+
namespace AutSoft.AspNetCore.Blazor.ComponentState;
6+
7+
/// <inheritdoc />
8+
public class ComponentStateStorage : IComponentStateStorage
9+
{
10+
private readonly Dictionary<string, List<StateEntry>> _currentComponentStates = new();
11+
12+
/// <inheritdoc />
13+
public void SaveStateForComponent(string instanceKey, ComponentBase component)
14+
{
15+
var componentType = component.GetType();
16+
17+
var componentStates = new List<StateEntry>();
18+
19+
var propertiesToSave = GetPropertiesFromHierarchy(componentType, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
20+
.Where(prop => prop.IsDefined(typeof(PreserveStateAttribute), false))
21+
.Where(prop => prop.GetValue(component) != null)
22+
.Select(prop => new StateEntry(prop, prop.GetValue(component)!))
23+
.ToList();
24+
25+
componentStates.AddRange(propertiesToSave);
26+
27+
var fieldsToSave = GetFieldsFromHierarchy(componentType, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
28+
.Where(field => field.IsDefined(typeof(PreserveStateAttribute), false))
29+
.Where(field => field.GetValue(component) != null)
30+
.Select(field => new StateEntry(field, field.GetValue(component)!))
31+
.ToList();
32+
33+
componentStates.AddRange(fieldsToSave);
34+
35+
_currentComponentStates[instanceKey] = componentStates;
36+
}
37+
38+
/// <inheritdoc />
39+
public void RestoreStateForComponent(string instanceKey, ComponentBase component)
40+
{
41+
if (!_currentComponentStates.ContainsKey(instanceKey))
42+
{
43+
return;
44+
}
45+
46+
foreach (var state in _currentComponentStates[instanceKey])
47+
{
48+
if (state.Member is PropertyInfo pi)
49+
{
50+
pi.SetValue(component, state.Value);
51+
}
52+
else if (state.Member is FieldInfo fi)
53+
{
54+
fi.SetValue(component, state.Value);
55+
}
56+
else
57+
{
58+
throw new NotSupportedException("Field type not supported!");
59+
}
60+
}
61+
}
62+
63+
/// <inheritdoc />
64+
public void ClearComponentStates()
65+
{
66+
_currentComponentStates.Clear();
67+
}
68+
69+
private IEnumerable<PropertyInfo> GetPropertiesFromHierarchy(Type type, BindingFlags bindingFlags)
70+
{
71+
foreach (var property in type.GetProperties(bindingFlags))
72+
{
73+
yield return property;
74+
}
75+
76+
if (type.BaseType == null)
77+
{
78+
yield break;
79+
}
80+
81+
foreach (var property in GetPropertiesFromHierarchy(type.BaseType, bindingFlags))
82+
{
83+
yield return property;
84+
}
85+
}
86+
87+
private IEnumerable<FieldInfo> GetFieldsFromHierarchy(Type type, BindingFlags bindingFlags)
88+
{
89+
foreach (var field in type.GetFields(bindingFlags))
90+
{
91+
yield return field;
92+
}
93+
94+
if (type.BaseType == null)
95+
{
96+
yield break;
97+
}
98+
99+
foreach (var field in GetFieldsFromHierarchy(type.BaseType, bindingFlags))
100+
{
101+
yield return field;
102+
}
103+
}
104+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using Microsoft.AspNetCore.Components;
2+
3+
namespace AutSoft.AspNetCore.Blazor.ComponentState;
4+
5+
/// <summary>
6+
/// State storage for component.
7+
/// </summary>
8+
public interface IComponentStateStorage
9+
{
10+
/// <summary>
11+
/// Saves the state of the component to the specified instance key.
12+
/// </summary>
13+
/// <param name="instanceKey">Key of the instance where to save.</param>
14+
/// <param name="component">Component to save.</param>
15+
void SaveStateForComponent(string instanceKey, ComponentBase component);
16+
17+
/// <summary>
18+
/// Restores the state of the component from the specified instance key.
19+
/// </summary>
20+
/// <param name="instanceKey">Key of the instance from which to reload.</param>
21+
/// <param name="component">Component to restore.</param>
22+
void RestoreStateForComponent(string instanceKey, ComponentBase component);
23+
24+
/// <summary>
25+
/// Clear all component states.
26+
/// </summary>
27+
void ClearComponentStates();
28+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using Microsoft.JSInterop;
2+
3+
using System.Globalization;
4+
5+
namespace AutSoft.AspNetCore.Blazor.ComponentState;
6+
7+
/// <summary>
8+
/// Extension methods for <see cref="IJSRuntime">IJSRuntime</see>.
9+
/// </summary>
10+
public static class JSRuntimeExtensions
11+
{
12+
/// <summary>
13+
/// Gets the navigation state time key.
14+
/// </summary>
15+
public static async ValueTask<string> GetNavStateTimeKeyAsync(this IJSRuntime jsRuntime) =>
16+
(await jsRuntime.InvokeAsync<long>("get_nav_state_time_key")).ToString(CultureInfo.InvariantCulture);
17+
}

0 commit comments

Comments
 (0)