commit
f3b152e8d1
32 changed files with 1877 additions and 0 deletions
@ -0,0 +1,2 @@ |
|||
# Auto detect text files and perform LF normalization |
|||
* text=auto |
|||
@ -0,0 +1,398 @@ |
|||
## Ignore Visual Studio temporary files, build results, and |
|||
## files generated by popular Visual Studio add-ons. |
|||
## |
|||
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore |
|||
|
|||
# User-specific files |
|||
*.rsuser |
|||
*.suo |
|||
*.user |
|||
*.userosscache |
|||
*.sln.docstates |
|||
|
|||
# User-specific files (MonoDevelop/Xamarin Studio) |
|||
*.userprefs |
|||
|
|||
# Mono auto generated files |
|||
mono_crash.* |
|||
|
|||
# Build results |
|||
[Dd]ebug/ |
|||
[Dd]ebugPublic/ |
|||
[Rr]elease/ |
|||
[Rr]eleases/ |
|||
x64/ |
|||
x86/ |
|||
[Ww][Ii][Nn]32/ |
|||
[Aa][Rr][Mm]/ |
|||
[Aa][Rr][Mm]64/ |
|||
bld/ |
|||
[Bb]in/ |
|||
[Oo]bj/ |
|||
[Ll]og/ |
|||
[Ll]ogs/ |
|||
|
|||
# Visual Studio 2015/2017 cache/options directory |
|||
.vs/ |
|||
# Uncomment if you have tasks that create the project's static files in wwwroot |
|||
#wwwroot/ |
|||
|
|||
# Visual Studio 2017 auto generated files |
|||
Generated\ Files/ |
|||
|
|||
# MSTest test Results |
|||
[Tt]est[Rr]esult*/ |
|||
[Bb]uild[Ll]og.* |
|||
|
|||
# NUnit |
|||
*.VisualState.xml |
|||
TestResult.xml |
|||
nunit-*.xml |
|||
|
|||
# Build Results of an ATL Project |
|||
[Dd]ebugPS/ |
|||
[Rr]eleasePS/ |
|||
dlldata.c |
|||
|
|||
# Benchmark Results |
|||
BenchmarkDotNet.Artifacts/ |
|||
|
|||
# .NET Core |
|||
project.lock.json |
|||
project.fragment.lock.json |
|||
artifacts/ |
|||
|
|||
# ASP.NET Scaffolding |
|||
ScaffoldingReadMe.txt |
|||
|
|||
# StyleCop |
|||
StyleCopReport.xml |
|||
|
|||
# Files built by Visual Studio |
|||
*_i.c |
|||
*_p.c |
|||
*_h.h |
|||
*.ilk |
|||
*.meta |
|||
*.obj |
|||
*.iobj |
|||
*.pch |
|||
*.pdb |
|||
*.ipdb |
|||
*.pgc |
|||
*.pgd |
|||
*.rsp |
|||
*.sbr |
|||
*.tlb |
|||
*.tli |
|||
*.tlh |
|||
*.tmp |
|||
*.tmp_proj |
|||
*_wpftmp.csproj |
|||
*.log |
|||
*.tlog |
|||
*.vspscc |
|||
*.vssscc |
|||
.builds |
|||
*.pidb |
|||
*.svclog |
|||
*.scc |
|||
|
|||
# Chutzpah Test files |
|||
_Chutzpah* |
|||
|
|||
# Visual C++ cache files |
|||
ipch/ |
|||
*.aps |
|||
*.ncb |
|||
*.opendb |
|||
*.opensdf |
|||
*.sdf |
|||
*.cachefile |
|||
*.VC.db |
|||
*.VC.VC.opendb |
|||
|
|||
# Visual Studio profiler |
|||
*.psess |
|||
*.vsp |
|||
*.vspx |
|||
*.sap |
|||
|
|||
# Visual Studio Trace Files |
|||
*.e2e |
|||
|
|||
# TFS 2012 Local Workspace |
|||
$tf/ |
|||
|
|||
# Guidance Automation Toolkit |
|||
*.gpState |
|||
|
|||
# ReSharper is a .NET coding add-in |
|||
_ReSharper*/ |
|||
*.[Rr]e[Ss]harper |
|||
*.DotSettings.user |
|||
|
|||
# TeamCity is a build add-in |
|||
_TeamCity* |
|||
|
|||
# DotCover is a Code Coverage Tool |
|||
*.dotCover |
|||
|
|||
# AxoCover is a Code Coverage Tool |
|||
.axoCover/* |
|||
!.axoCover/settings.json |
|||
|
|||
# Coverlet is a free, cross platform Code Coverage Tool |
|||
coverage*.json |
|||
coverage*.xml |
|||
coverage*.info |
|||
|
|||
# Visual Studio code coverage results |
|||
*.coverage |
|||
*.coveragexml |
|||
|
|||
# NCrunch |
|||
_NCrunch_* |
|||
.*crunch*.local.xml |
|||
nCrunchTemp_* |
|||
|
|||
# MightyMoose |
|||
*.mm.* |
|||
AutoTest.Net/ |
|||
|
|||
# Web workbench (sass) |
|||
.sass-cache/ |
|||
|
|||
# Installshield output folder |
|||
[Ee]xpress/ |
|||
|
|||
# DocProject is a documentation generator add-in |
|||
DocProject/buildhelp/ |
|||
DocProject/Help/*.HxT |
|||
DocProject/Help/*.HxC |
|||
DocProject/Help/*.hhc |
|||
DocProject/Help/*.hhk |
|||
DocProject/Help/*.hhp |
|||
DocProject/Help/Html2 |
|||
DocProject/Help/html |
|||
|
|||
# Click-Once directory |
|||
publish/ |
|||
|
|||
# Publish Web Output |
|||
*.[Pp]ublish.xml |
|||
*.azurePubxml |
|||
# Note: Comment the next line if you want to checkin your web deploy settings, |
|||
# but database connection strings (with potential passwords) will be unencrypted |
|||
*.pubxml |
|||
*.publishproj |
|||
|
|||
# Microsoft Azure Web App publish settings. Comment the next line if you want to |
|||
# checkin your Azure Web App publish settings, but sensitive information contained |
|||
# in these scripts will be unencrypted |
|||
PublishScripts/ |
|||
|
|||
# NuGet Packages |
|||
*.nupkg |
|||
# NuGet Symbol Packages |
|||
*.snupkg |
|||
# The packages folder can be ignored because of Package Restore |
|||
**/[Pp]ackages/* |
|||
# except build/, which is used as an MSBuild target. |
|||
!**/[Pp]ackages/build/ |
|||
# Uncomment if necessary however generally it will be regenerated when needed |
|||
#!**/[Pp]ackages/repositories.config |
|||
# NuGet v3's project.json files produces more ignorable files |
|||
*.nuget.props |
|||
*.nuget.targets |
|||
|
|||
# Microsoft Azure Build Output |
|||
csx/ |
|||
*.build.csdef |
|||
|
|||
# Microsoft Azure Emulator |
|||
ecf/ |
|||
rcf/ |
|||
|
|||
# Windows Store app package directories and files |
|||
AppPackages/ |
|||
BundleArtifacts/ |
|||
Package.StoreAssociation.xml |
|||
_pkginfo.txt |
|||
*.appx |
|||
*.appxbundle |
|||
*.appxupload |
|||
|
|||
# Visual Studio cache files |
|||
# files ending in .cache can be ignored |
|||
*.[Cc]ache |
|||
# but keep track of directories ending in .cache |
|||
!?*.[Cc]ache/ |
|||
|
|||
# Others |
|||
ClientBin/ |
|||
~$* |
|||
*~ |
|||
*.dbmdl |
|||
*.dbproj.schemaview |
|||
*.jfm |
|||
*.pfx |
|||
*.publishsettings |
|||
orleans.codegen.cs |
|||
|
|||
# Including strong name files can present a security risk |
|||
# (https://github.com/github/gitignore/pull/2483#issue-259490424) |
|||
#*.snk |
|||
|
|||
# Since there are multiple workflows, uncomment next line to ignore bower_components |
|||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) |
|||
#bower_components/ |
|||
|
|||
# RIA/Silverlight projects |
|||
Generated_Code/ |
|||
|
|||
# Backup & report files from converting an old project file |
|||
# to a newer Visual Studio version. Backup files are not needed, |
|||
# because we have git ;-) |
|||
_UpgradeReport_Files/ |
|||
Backup*/ |
|||
UpgradeLog*.XML |
|||
UpgradeLog*.htm |
|||
ServiceFabricBackup/ |
|||
*.rptproj.bak |
|||
|
|||
# SQL Server files |
|||
*.mdf |
|||
*.ldf |
|||
*.ndf |
|||
|
|||
# Business Intelligence projects |
|||
*.rdl.data |
|||
*.bim.layout |
|||
*.bim_*.settings |
|||
*.rptproj.rsuser |
|||
*- [Bb]ackup.rdl |
|||
*- [Bb]ackup ([0-9]).rdl |
|||
*- [Bb]ackup ([0-9][0-9]).rdl |
|||
|
|||
# Microsoft Fakes |
|||
FakesAssemblies/ |
|||
|
|||
# GhostDoc plugin setting file |
|||
*.GhostDoc.xml |
|||
|
|||
# Node.js Tools for Visual Studio |
|||
.ntvs_analysis.dat |
|||
node_modules/ |
|||
|
|||
# Visual Studio 6 build log |
|||
*.plg |
|||
|
|||
# Visual Studio 6 workspace options file |
|||
*.opt |
|||
|
|||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) |
|||
*.vbw |
|||
|
|||
# Visual Studio 6 auto-generated project file (contains which files were open etc.) |
|||
*.vbp |
|||
|
|||
# Visual Studio 6 workspace and project file (working project files containing files to include in project) |
|||
*.dsw |
|||
*.dsp |
|||
|
|||
# Visual Studio 6 technical files |
|||
*.ncb |
|||
*.aps |
|||
|
|||
# Visual Studio LightSwitch build output |
|||
**/*.HTMLClient/GeneratedArtifacts |
|||
**/*.DesktopClient/GeneratedArtifacts |
|||
**/*.DesktopClient/ModelManifest.xml |
|||
**/*.Server/GeneratedArtifacts |
|||
**/*.Server/ModelManifest.xml |
|||
_Pvt_Extensions |
|||
|
|||
# Paket dependency manager |
|||
.paket/paket.exe |
|||
paket-files/ |
|||
|
|||
# FAKE - F# Make |
|||
.fake/ |
|||
|
|||
# CodeRush personal settings |
|||
.cr/personal |
|||
|
|||
# Python Tools for Visual Studio (PTVS) |
|||
__pycache__/ |
|||
*.pyc |
|||
|
|||
# Cake - Uncomment if you are using it |
|||
# tools/** |
|||
# !tools/packages.config |
|||
|
|||
# Tabs Studio |
|||
*.tss |
|||
|
|||
# Telerik's JustMock configuration file |
|||
*.jmconfig |
|||
|
|||
# BizTalk build output |
|||
*.btp.cs |
|||
*.btm.cs |
|||
*.odx.cs |
|||
*.xsd.cs |
|||
|
|||
# OpenCover UI analysis results |
|||
OpenCover/ |
|||
|
|||
# Azure Stream Analytics local run output |
|||
ASALocalRun/ |
|||
|
|||
# MSBuild Binary and Structured Log |
|||
*.binlog |
|||
|
|||
# NVidia Nsight GPU debugger configuration file |
|||
*.nvuser |
|||
|
|||
# MFractors (Xamarin productivity tool) working folder |
|||
.mfractor/ |
|||
|
|||
# Local History for Visual Studio |
|||
.localhistory/ |
|||
|
|||
# Visual Studio History (VSHistory) files |
|||
.vshistory/ |
|||
|
|||
# BeatPulse healthcheck temp database |
|||
healthchecksdb |
|||
|
|||
# Backup folder for Package Reference Convert tool in Visual Studio 2017 |
|||
MigrationBackup/ |
|||
|
|||
# Ionide (cross platform F# VS Code tools) working folder |
|||
.ionide/ |
|||
|
|||
# Fody - auto-generated XML schema |
|||
FodyWeavers.xsd |
|||
|
|||
# VS Code files for those working on multiple tools |
|||
.vscode/* |
|||
!.vscode/settings.json |
|||
!.vscode/tasks.json |
|||
!.vscode/launch.json |
|||
!.vscode/extensions.json |
|||
*.code-workspace |
|||
|
|||
# Local History for Visual Studio Code |
|||
.history/ |
|||
|
|||
# Windows Installer files from build outputs |
|||
*.cab |
|||
*.msi |
|||
*.msix |
|||
*.msm |
|||
*.msp |
|||
|
|||
# JetBrains Rider |
|||
*.sln.iml |
|||
@ -0,0 +1,13 @@ |
|||
# Default ignored files |
|||
/shelf/ |
|||
/workspace.xml |
|||
# Rider ignored files |
|||
/projectSettingsUpdater.xml |
|||
/contentModel.xml |
|||
/.idea.lsw.Abp.AntDesignUI.iml |
|||
/modules.xml |
|||
# Editor-based HTTP Client requests |
|||
/httpRequests/ |
|||
# Datasource local storage ignored files |
|||
/dataSources/ |
|||
/dataSources.local.xml |
|||
@ -0,0 +1,4 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project version="4"> |
|||
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" /> |
|||
</project> |
|||
@ -0,0 +1,8 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project version="4"> |
|||
<component name="UserContentModel"> |
|||
<attachedFolders /> |
|||
<explicitIncludes /> |
|||
<explicitExcludes /> |
|||
</component> |
|||
</project> |
|||
@ -0,0 +1,21 @@ |
|||
MIT License |
|||
|
|||
Copyright (c) 2022 liangshiwei |
|||
|
|||
Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
of this software and associated documentation files (the "Software"), to deal |
|||
in the Software without restriction, including without limitation the rights |
|||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
copies of the Software, and to permit persons to whom the Software is |
|||
furnished to do so, subject to the following conditions: |
|||
|
|||
The above copyright notice and this permission notice shall be included in all |
|||
copies or substantial portions of the Software. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|||
SOFTWARE. |
|||
@ -0,0 +1,2 @@ |
|||
# Lsw.Abp.AntDesignUI |
|||
|
|||
@ -0,0 +1,9 @@ |
|||
<Project> |
|||
<ItemGroup> |
|||
<PackageReference Include="ConfigureAwait.Fody" Version="3.3.1" PrivateAssets="All" /> |
|||
<PackageReference Include="Fody" Version="6.5.3"> |
|||
<PrivateAssets>All</PrivateAssets> |
|||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> |
|||
</PackageReference> |
|||
</ItemGroup> |
|||
</Project> |
|||
@ -0,0 +1,21 @@ |
|||
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00 |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{6C9F4322-BDC7-42DA-ACBD-1AC641B907B4}" |
|||
EndProject |
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lsw.Abp.AntDesignUI", "src\Lsw.Abp.AntDesignUI\Lsw.Abp.AntDesignUI.csproj", "{9EA4AA35-DEFC-4C25-8333-78137853EC5D}" |
|||
EndProject |
|||
Global |
|||
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
|||
Debug|Any CPU = Debug|Any CPU |
|||
Release|Any CPU = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(NestedProjects) = preSolution |
|||
{9EA4AA35-DEFC-4C25-8333-78137853EC5D} = {6C9F4322-BDC7-42DA-ACBD-1AC641B907B4} |
|||
EndGlobalSection |
|||
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
|||
{9EA4AA35-DEFC-4C25-8333-78137853EC5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{9EA4AA35-DEFC-4C25-8333-78137853EC5D}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{9EA4AA35-DEFC-4C25-8333-78137853EC5D}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{9EA4AA35-DEFC-4C25-8333-78137853EC5D}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
EndGlobalSection |
|||
EndGlobal |
|||
@ -0,0 +1,19 @@ |
|||
using Blazorise; |
|||
|
|||
namespace Lsw.Abp.AntDesignUI; |
|||
|
|||
public class BreadcrumbItem |
|||
{ |
|||
public string Text { get; set; } |
|||
|
|||
public object Icon { get; set; } |
|||
|
|||
public string Url { get; set; } |
|||
|
|||
public BreadcrumbItem(string text, string url = null, object icon = null) |
|||
{ |
|||
Text = text; |
|||
Url = url; |
|||
Icon = icon; |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Application; |
|||
using Volo.Abp.AspNetCore.Components.Web; |
|||
using Volo.Abp.Authorization; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Lsw.Abp.AntDesignUI; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpAspNetCoreComponentsWebModule), |
|||
typeof(AbpDddApplicationContractsModule), |
|||
typeof(AbpAuthorizationModule) |
|||
)] |
|||
public class AbpAntDesignUIModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddAntDesign(); |
|||
} |
|||
} |
|||
@ -0,0 +1,595 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using AntDesign; |
|||
using AntDesign.TableModels; |
|||
using JetBrains.Annotations; |
|||
using Localization.Resources.AbpUi; |
|||
using Lsw.Abp.AntDesignUI.Components; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.AspNetCore.Components; |
|||
using Microsoft.AspNetCore.Components.Web; |
|||
using Microsoft.Extensions.Localization; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.Abp.AspNetCore.Components; |
|||
using Volo.Abp.AspNetCore.Components.Web.Extensibility.EntityActions; |
|||
using Volo.Abp.AspNetCore.Components.Web.Extensibility.TableColumns; |
|||
using Volo.Abp.Authorization; |
|||
|
|||
namespace Lsw.Abp.AntDesignUI; |
|||
|
|||
public abstract class AbpCrudPageBase< |
|||
TAppService, |
|||
TEntityDto, |
|||
TKey> |
|||
: AbpCrudPageBase< |
|||
TAppService, |
|||
TEntityDto, |
|||
TKey, |
|||
PagedAndSortedResultRequestDto> |
|||
where TAppService : ICrudAppService< |
|||
TEntityDto, |
|||
TKey> |
|||
where TEntityDto : class, IEntityDto<TKey>, new() |
|||
{ |
|||
} |
|||
|
|||
public abstract class AbpCrudPageBase< |
|||
TAppService, |
|||
TEntityDto, |
|||
TKey, |
|||
TGetListInput> |
|||
: AbpCrudPageBase< |
|||
TAppService, |
|||
TEntityDto, |
|||
TKey, |
|||
TGetListInput, |
|||
TEntityDto> |
|||
where TAppService : ICrudAppService< |
|||
TEntityDto, |
|||
TKey, |
|||
TGetListInput> |
|||
where TEntityDto : class, IEntityDto<TKey>, new() |
|||
where TGetListInput : new() |
|||
{ |
|||
} |
|||
|
|||
public abstract class AbpCrudPageBase< |
|||
TAppService, |
|||
TEntityDto, |
|||
TKey, |
|||
TGetListInput, |
|||
TCreateInput> |
|||
: AbpCrudPageBase< |
|||
TAppService, |
|||
TEntityDto, |
|||
TKey, |
|||
TGetListInput, |
|||
TCreateInput, |
|||
TCreateInput> |
|||
where TAppService : ICrudAppService< |
|||
TEntityDto, |
|||
TKey, |
|||
TGetListInput, |
|||
TCreateInput> |
|||
where TEntityDto : IEntityDto<TKey> |
|||
where TCreateInput : class, new() |
|||
where TGetListInput : new() |
|||
{ |
|||
} |
|||
|
|||
public abstract class AbpCrudPageBase< |
|||
TAppService, |
|||
TEntityDto, |
|||
TKey, |
|||
TGetListInput, |
|||
TCreateInput, |
|||
TUpdateInput> |
|||
: AbpCrudPageBase< |
|||
TAppService, |
|||
TEntityDto, |
|||
TEntityDto, |
|||
TKey, |
|||
TGetListInput, |
|||
TCreateInput, |
|||
TUpdateInput> |
|||
where TAppService : ICrudAppService< |
|||
TEntityDto, |
|||
TKey, |
|||
TGetListInput, |
|||
TCreateInput, |
|||
TUpdateInput> |
|||
where TEntityDto : IEntityDto<TKey> |
|||
where TCreateInput : class, new() |
|||
where TUpdateInput : class, new() |
|||
where TGetListInput : new() |
|||
{ |
|||
} |
|||
|
|||
public abstract class AbpCrudPageBase< |
|||
TAppService, |
|||
TGetOutputDto, |
|||
TGetListOutputDto, |
|||
TKey, |
|||
TGetListInput, |
|||
TCreateInput, |
|||
TUpdateInput> |
|||
: AbpCrudPageBase< |
|||
TAppService, |
|||
TGetOutputDto, |
|||
TGetListOutputDto, |
|||
TKey, |
|||
TGetListInput, |
|||
TCreateInput, |
|||
TUpdateInput, |
|||
TGetListOutputDto, |
|||
TCreateInput, |
|||
TUpdateInput> |
|||
where TAppService : ICrudAppService< |
|||
TGetOutputDto, |
|||
TGetListOutputDto, |
|||
TKey, |
|||
TGetListInput, |
|||
TCreateInput, |
|||
TUpdateInput> |
|||
where TGetOutputDto : IEntityDto<TKey> |
|||
where TGetListOutputDto : IEntityDto<TKey> |
|||
where TCreateInput : class, new() |
|||
where TUpdateInput : class, new() |
|||
where TGetListInput : new() |
|||
{ |
|||
} |
|||
|
|||
public abstract class AbpCrudPageBase< |
|||
TAppService, |
|||
TGetOutputDto, |
|||
TGetListOutputDto, |
|||
TKey, |
|||
TGetListInput, |
|||
TCreateInput, |
|||
TUpdateInput, |
|||
TListViewModel, |
|||
TCreateViewModel, |
|||
TUpdateViewModel> |
|||
: AbpComponentBase |
|||
where TAppService : ICrudAppService< |
|||
TGetOutputDto, |
|||
TGetListOutputDto, |
|||
TKey, |
|||
TGetListInput, |
|||
TCreateInput, |
|||
TUpdateInput> |
|||
where TGetOutputDto : IEntityDto<TKey> |
|||
where TGetListOutputDto : IEntityDto<TKey> |
|||
where TCreateInput : class |
|||
where TUpdateInput : class |
|||
where TGetListInput : new() |
|||
where TListViewModel : IEntityDto<TKey> |
|||
where TCreateViewModel : class, new() |
|||
where TUpdateViewModel : class, new() |
|||
{ |
|||
[Inject] protected TAppService AppService { get; set; } |
|||
|
|||
[Inject] protected IStringLocalizer<AbpUiResource> UiLocalizer { get; set; } |
|||
|
|||
protected virtual int PageSize { get; } = LimitedResultRequestDto.DefaultMaxResultCount; |
|||
|
|||
protected int CurrentPage = 1; |
|||
protected string CurrentSorting; |
|||
protected int? TotalCount; |
|||
protected bool Loading = false; |
|||
protected TGetListInput GetListInput = new(); |
|||
protected IReadOnlyList<TListViewModel> Entities = Array.Empty<TListViewModel>(); |
|||
protected TCreateViewModel NewEntity; |
|||
protected TKey EditingEntityId; |
|||
protected TUpdateViewModel EditingEntity; |
|||
protected Modal CreateModal; |
|||
protected bool CreateModalVisible; |
|||
protected Modal EditModal; |
|||
protected bool EditModalVisible; |
|||
protected Form<TCreateViewModel> CreateFormRef; |
|||
protected Form<TUpdateViewModel> EditFormRef; |
|||
protected List<BreadcrumbItem> BreadcrumbItems = new(2); |
|||
protected TableEntityActionsColumn<TListViewModel> EntityActionsColumn; |
|||
protected EntityActionDictionary EntityActions { get; set; } |
|||
protected TableColumnDictionary TableColumns { get; set; } |
|||
|
|||
protected string CreatePolicyName { get; set; } |
|||
protected string UpdatePolicyName { get; set; } |
|||
protected string DeletePolicyName { get; set; } |
|||
|
|||
public bool HasCreatePermission { get; set; } |
|||
public bool HasUpdatePermission { get; set; } |
|||
public bool HasDeletePermission { get; set; } |
|||
|
|||
protected AbpCrudPageBase() |
|||
{ |
|||
NewEntity = new TCreateViewModel(); |
|||
EditingEntity = new TUpdateViewModel(); |
|||
TableColumns = new TableColumnDictionary(); |
|||
EntityActions = new EntityActionDictionary(); |
|||
} |
|||
|
|||
protected override async Task OnInitializedAsync() |
|||
{ |
|||
await SetPermissionsAsync(); |
|||
await SetEntityActionsAsync(); |
|||
await SetTableColumnsAsync(); |
|||
await InvokeAsync(StateHasChanged); |
|||
} |
|||
|
|||
protected override async Task OnAfterRenderAsync(bool firstRender) |
|||
{ |
|||
if (firstRender) |
|||
{ |
|||
await base.OnAfterRenderAsync(true); |
|||
await SetToolbarItemsAsync(); |
|||
await SetBreadcrumbItemsAsync(); |
|||
} |
|||
} |
|||
|
|||
protected virtual async Task SetPermissionsAsync() |
|||
{ |
|||
if (CreatePolicyName != null) |
|||
{ |
|||
HasCreatePermission = await AuthorizationService.IsGrantedAsync(CreatePolicyName); |
|||
} |
|||
|
|||
if (UpdatePolicyName != null) |
|||
{ |
|||
HasUpdatePermission = await AuthorizationService.IsGrantedAsync(UpdatePolicyName); |
|||
} |
|||
|
|||
if (DeletePolicyName != null) |
|||
{ |
|||
HasDeletePermission = await AuthorizationService.IsGrantedAsync(DeletePolicyName); |
|||
} |
|||
} |
|||
|
|||
protected virtual async Task GetEntitiesAsync() |
|||
{ |
|||
try |
|||
{ |
|||
Loading = true; |
|||
await UpdateGetListInputAsync(); |
|||
var result = await AppService.GetListAsync(GetListInput); |
|||
Entities = MapToListViewModel(result.Items); |
|||
TotalCount = (int?)result.TotalCount; |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
await HandleErrorAsync(ex); |
|||
} |
|||
|
|||
Loading = false; |
|||
} |
|||
|
|||
private IReadOnlyList<TListViewModel> MapToListViewModel(IReadOnlyList<TGetListOutputDto> dtos) |
|||
{ |
|||
if (typeof(TGetListOutputDto) == typeof(TListViewModel)) |
|||
{ |
|||
return dtos.As<IReadOnlyList<TListViewModel>>(); |
|||
} |
|||
|
|||
return ObjectMapper.Map<IReadOnlyList<TGetListOutputDto>, List<TListViewModel>>(dtos); |
|||
} |
|||
|
|||
protected virtual Task UpdateGetListInputAsync() |
|||
{ |
|||
if (GetListInput is ISortedResultRequest sortedResultRequestInput) |
|||
{ |
|||
sortedResultRequestInput.Sorting = CurrentSorting; |
|||
} |
|||
|
|||
if (GetListInput is IPagedResultRequest pagedResultRequestInput) |
|||
{ |
|||
pagedResultRequestInput.SkipCount = (CurrentPage - 1) * PageSize; |
|||
} |
|||
|
|||
if (GetListInput is ILimitedResultRequest limitedResultRequestInput) |
|||
{ |
|||
limitedResultRequestInput.MaxResultCount = PageSize; |
|||
} |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
protected virtual async Task SearchEntitiesAsync() |
|||
{ |
|||
CurrentPage = 1; |
|||
|
|||
await GetEntitiesAsync(); |
|||
|
|||
await InvokeAsync(StateHasChanged); |
|||
} |
|||
|
|||
protected virtual async Task OnDataGridReadAsync(QueryModel<TListViewModel> e) |
|||
{ |
|||
CurrentSorting = e.SortModel |
|||
.Select(c => c.FieldName + (c.Sort == "descend" ? " DESC" : "")) |
|||
.JoinAsString(","); |
|||
CurrentPage = e.PageIndex; |
|||
|
|||
await GetEntitiesAsync(); |
|||
|
|||
await InvokeAsync(StateHasChanged); |
|||
} |
|||
|
|||
protected virtual async Task OpenCreateModalAsync() |
|||
{ |
|||
try |
|||
{ |
|||
CreateFormRef.Reset(); |
|||
|
|||
await CheckCreatePolicyAsync(); |
|||
|
|||
NewEntity = new TCreateViewModel(); |
|||
|
|||
await InvokeAsync(() => |
|||
{ |
|||
StateHasChanged(); |
|||
CreateModalVisible = true; |
|||
|
|||
return Task.CompletedTask; |
|||
}); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
await HandleErrorAsync(ex); |
|||
} |
|||
} |
|||
|
|||
protected virtual Task CloseCreateModalAsync() |
|||
{ |
|||
NewEntity = new TCreateViewModel(); |
|||
|
|||
return InvokeAsync(() => |
|||
{ |
|||
CreateModalVisible = false; |
|||
}); |
|||
} |
|||
|
|||
protected virtual Task ClosingCreateModal(MouseEventArgs eventArgs) |
|||
{ |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
protected virtual async Task OpenEditModalAsync(TListViewModel entity) |
|||
{ |
|||
try |
|||
{ |
|||
EditFormRef.Reset(); |
|||
|
|||
await CheckUpdatePolicyAsync(); |
|||
|
|||
var entityDto = await AppService.GetAsync(entity.Id); |
|||
|
|||
EditingEntityId = entity.Id; |
|||
EditingEntity = MapToEditingEntity(entityDto); |
|||
|
|||
await InvokeAsync(() => |
|||
{ |
|||
StateHasChanged(); |
|||
EditModalVisible = true; |
|||
|
|||
return Task.CompletedTask; |
|||
}); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
await HandleErrorAsync(ex); |
|||
} |
|||
} |
|||
|
|||
protected virtual TUpdateViewModel MapToEditingEntity(TGetOutputDto entityDto) |
|||
{ |
|||
return ObjectMapper.Map<TGetOutputDto, TUpdateViewModel>(entityDto); |
|||
} |
|||
|
|||
protected virtual TCreateInput MapToCreateInput(TCreateViewModel createViewModel) |
|||
{ |
|||
if (typeof(TCreateInput) == typeof(TCreateViewModel)) |
|||
{ |
|||
return createViewModel.As<TCreateInput>(); |
|||
} |
|||
|
|||
return ObjectMapper.Map<TCreateViewModel, TCreateInput>(createViewModel); |
|||
} |
|||
|
|||
protected virtual TUpdateInput MapToUpdateInput(TUpdateViewModel updateViewModel) |
|||
{ |
|||
if (typeof(TUpdateInput) == typeof(TUpdateViewModel)) |
|||
{ |
|||
return updateViewModel.As<TUpdateInput>(); |
|||
} |
|||
|
|||
return ObjectMapper.Map<TUpdateViewModel, TUpdateInput>(updateViewModel); |
|||
} |
|||
|
|||
protected virtual Task CloseEditModalAsync() |
|||
{ |
|||
InvokeAsync(() => |
|||
{ |
|||
EditModalVisible = false; |
|||
}); |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
protected virtual Task ClosingEditModal(MouseEventArgs eventArgs) |
|||
{ |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
protected virtual async Task CreateEntityAsync() |
|||
{ |
|||
try |
|||
{ |
|||
var validate = true; |
|||
if (CreateFormRef != null) |
|||
{ |
|||
validate = CreateFormRef.Validate(); |
|||
} |
|||
|
|||
if (validate) |
|||
{ |
|||
await OnCreatingEntityAsync(); |
|||
|
|||
await CheckCreatePolicyAsync(); |
|||
var createInput = MapToCreateInput(NewEntity); |
|||
await AppService.CreateAsync(createInput); |
|||
|
|||
await OnCreatedEntityAsync(); |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
await HandleErrorAsync(ex); |
|||
} |
|||
} |
|||
|
|||
protected virtual Task OnCreatingEntityAsync() |
|||
{ |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
protected virtual async Task OnCreatedEntityAsync() |
|||
{ |
|||
NewEntity = new TCreateViewModel(); |
|||
await GetEntitiesAsync(); |
|||
|
|||
await InvokeAsync(() => |
|||
{ |
|||
CreateModalVisible = false; |
|||
}); |
|||
} |
|||
|
|||
protected virtual async Task UpdateEntityAsync() |
|||
{ |
|||
try |
|||
{ |
|||
var validate = true; |
|||
if (EditFormRef != null) |
|||
{ |
|||
validate = EditFormRef.Validate(); |
|||
} |
|||
|
|||
if (validate) |
|||
{ |
|||
await OnUpdatingEntityAsync(); |
|||
|
|||
await CheckUpdatePolicyAsync(); |
|||
var updateInput = MapToUpdateInput(EditingEntity); |
|||
await AppService.UpdateAsync(EditingEntityId, updateInput); |
|||
|
|||
await OnUpdatedEntityAsync(); |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
await HandleErrorAsync(ex); |
|||
} |
|||
} |
|||
|
|||
protected virtual Task OnUpdatingEntityAsync() |
|||
{ |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
protected virtual async Task OnUpdatedEntityAsync() |
|||
{ |
|||
await GetEntitiesAsync(); |
|||
|
|||
await InvokeAsync(() => |
|||
{ |
|||
EditModalVisible = false; |
|||
}); |
|||
} |
|||
|
|||
protected virtual async Task DeleteEntityAsync(TListViewModel entity) |
|||
{ |
|||
try |
|||
{ |
|||
await CheckDeletePolicyAsync(); |
|||
await OnDeletingEntityAsync(); |
|||
await AppService.DeleteAsync(entity.Id); |
|||
await OnDeletedEntityAsync(); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
await HandleErrorAsync(ex); |
|||
} |
|||
} |
|||
|
|||
protected virtual Task OnDeletingEntityAsync() |
|||
{ |
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
protected virtual async Task OnDeletedEntityAsync() |
|||
{ |
|||
await GetEntitiesAsync(); |
|||
await InvokeAsync(StateHasChanged); |
|||
await Notify.Success(L["SuccessfullyDeleted"]); |
|||
} |
|||
|
|||
protected virtual string GetDeleteConfirmationMessage(TListViewModel entity) |
|||
{ |
|||
return UiLocalizer["ItemWillBeDeletedMessage"]; |
|||
} |
|||
|
|||
protected virtual async Task CheckCreatePolicyAsync() |
|||
{ |
|||
await CheckPolicyAsync(CreatePolicyName); |
|||
} |
|||
|
|||
protected virtual async Task CheckUpdatePolicyAsync() |
|||
{ |
|||
await CheckPolicyAsync(UpdatePolicyName); |
|||
} |
|||
|
|||
protected virtual async Task CheckDeletePolicyAsync() |
|||
{ |
|||
await CheckPolicyAsync(DeletePolicyName); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Calls IAuthorizationService.CheckAsync for the given <paramref name="policyName"/>.
|
|||
/// Throws <see cref="AbpAuthorizationException"/> if given policy was not granted for the current user.
|
|||
///
|
|||
/// Does nothing if <paramref name="policyName"/> is null or empty.
|
|||
/// </summary>
|
|||
/// <param name="policyName">A policy name to check</param>
|
|||
protected virtual async Task CheckPolicyAsync([CanBeNull] string policyName) |
|||
{ |
|||
if (string.IsNullOrEmpty(policyName)) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
await AuthorizationService.CheckAsync(policyName); |
|||
} |
|||
|
|||
protected virtual ValueTask SetBreadcrumbItemsAsync() |
|||
{ |
|||
return ValueTask.CompletedTask; |
|||
} |
|||
|
|||
protected virtual ValueTask SetEntityActionsAsync() |
|||
{ |
|||
return ValueTask.CompletedTask; |
|||
} |
|||
|
|||
protected virtual ValueTask SetTableColumnsAsync() |
|||
{ |
|||
return ValueTask.CompletedTask; |
|||
} |
|||
|
|||
protected virtual ValueTask SetToolbarItemsAsync() |
|||
{ |
|||
return ValueTask.CompletedTask; |
|||
} |
|||
} |
|||
|
|||
|
|||
@ -0,0 +1,8 @@ |
|||
using AntDesign; |
|||
|
|||
namespace Lsw.Abp.AntDesignUI; |
|||
|
|||
public static class AntDesignExtensions |
|||
{ |
|||
|
|||
} |
|||
@ -0,0 +1,98 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using AntDesign; |
|||
using Localization.Resources.AbpUi; |
|||
using Microsoft.AspNetCore.Components; |
|||
using Microsoft.Extensions.Localization; |
|||
using Volo.Abp.AspNetCore.Components.Messages; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Lsw.Abp.AntDesignUI; |
|||
|
|||
[Dependency(ReplaceServices = true)] |
|||
public class AntDesignUiMessageService : IUiMessageService , IScopedDependency |
|||
{ |
|||
[Inject] |
|||
public ConfirmService ConfirmService { get; set; } |
|||
|
|||
[Inject] |
|||
public ModalService ModalService { get; set; } |
|||
|
|||
private readonly IStringLocalizer<AbpUiResource> _localizer; |
|||
|
|||
public AntDesignUiMessageService(IStringLocalizer<AbpUiResource> localizer) |
|||
{ |
|||
_localizer = localizer; |
|||
} |
|||
|
|||
public async Task Info(string message, string title = null, Action<UiMessageOptions> options = null) |
|||
{ |
|||
var uiMessageOptions = CreateDefaultOptions(); |
|||
options?.Invoke(uiMessageOptions); |
|||
|
|||
await ModalService.InfoAsync(CreateConfirmOptions(message, title ?? _localizer["Info"], uiMessageOptions, ConfirmButtons.OK)); |
|||
} |
|||
|
|||
public async Task Success(string message, string title = null, Action<UiMessageOptions> options = null) |
|||
{ |
|||
var uiMessageOptions = CreateDefaultOptions(); |
|||
options?.Invoke(uiMessageOptions); |
|||
|
|||
await ModalService.SuccessAsync(CreateConfirmOptions(message, title ?? _localizer["Success"], uiMessageOptions, ConfirmButtons.OK)); |
|||
} |
|||
|
|||
public async Task Warn(string message, string title = null, Action<UiMessageOptions> options = null) |
|||
{ |
|||
var uiMessageOptions = CreateDefaultOptions(); |
|||
options?.Invoke(uiMessageOptions); |
|||
|
|||
await ModalService.WarningAsync(CreateConfirmOptions(message, title ?? _localizer["Warn"], uiMessageOptions, ConfirmButtons.YesNo)); |
|||
} |
|||
|
|||
public async Task Error(string message, string title = null, Action<UiMessageOptions> options = null) |
|||
{ |
|||
var uiMessageOptions = CreateDefaultOptions(); |
|||
options?.Invoke(uiMessageOptions); |
|||
|
|||
await ModalService.ErrorAsync(CreateConfirmOptions(message, title ?? _localizer["Error"], uiMessageOptions, ConfirmButtons.YesNo)); |
|||
} |
|||
|
|||
public async Task<bool> Confirm(string message, string title = null, Action<UiMessageOptions> options = null) |
|||
{ |
|||
var uiMessageOptions = CreateDefaultOptions(); |
|||
options?.Invoke(uiMessageOptions); |
|||
|
|||
return await ModalService.ConfirmAsync(CreateConfirmOptions(message, title ?? _localizer["Confirm"], uiMessageOptions, ConfirmButtons.YesNo)); |
|||
} |
|||
|
|||
protected virtual ConfirmOptions CreateConfirmOptions(string message, string title, UiMessageOptions uiMessageOptions, ConfirmButtons confirmButtons) |
|||
{ |
|||
var options = new ConfirmOptions |
|||
{ |
|||
OkText = uiMessageOptions.ConfirmButtonText, |
|||
CancelText = uiMessageOptions.CancelButtonText, |
|||
Content = message, |
|||
Title = title |
|||
}; |
|||
|
|||
if (confirmButtons == ConfirmButtons.YesNoCancel) |
|||
{ |
|||
options.Button2Props.ChildContent = uiMessageOptions.OkButtonText; |
|||
options.Button3Props.ChildContent = uiMessageOptions.CancelButtonText; |
|||
} |
|||
|
|||
return options; |
|||
} |
|||
|
|||
protected virtual UiMessageOptions CreateDefaultOptions() |
|||
{ |
|||
return new UiMessageOptions |
|||
{ |
|||
CenterMessage = true, |
|||
ShowMessageIcon = true, |
|||
OkButtonText = _localizer["Ok"], |
|||
CancelButtonText = _localizer["Cancel"], |
|||
ConfirmButtonText = _localizer["Yes"], |
|||
}; |
|||
} |
|||
} |
|||
@ -0,0 +1,72 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using AntDesign; |
|||
using Localization.Resources.AbpUi; |
|||
using Microsoft.AspNetCore.Components; |
|||
using Microsoft.Extensions.Localization; |
|||
using Volo.Abp.AspNetCore.Components.Notifications; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Lsw.Abp.AntDesignUI; |
|||
|
|||
[Dependency(ReplaceServices = true)] |
|||
public class AntDesignUiNotificationService: IUiNotificationService, IScopedDependency |
|||
{ |
|||
[Inject] |
|||
protected NotificationService NoticeService { get; set; } |
|||
|
|||
private readonly IStringLocalizer<AbpUiResource> _localizer; |
|||
|
|||
public AntDesignUiNotificationService(IStringLocalizer<AbpUiResource> localizer) |
|||
{ |
|||
_localizer = localizer; |
|||
} |
|||
|
|||
public async Task Info(string message, string title = null, Action<UiNotificationOptions> options = null) |
|||
{ |
|||
var uiNotificationOptions = CreateDefaultOptions(); |
|||
options?.Invoke(uiNotificationOptions); |
|||
|
|||
await Notify(title ?? _localizer["Info"], message, NotificationType.Info); |
|||
} |
|||
|
|||
public async Task Success(string message, string title = null, Action<UiNotificationOptions> options = null) |
|||
{ |
|||
var uiNotificationOptions = CreateDefaultOptions(); |
|||
options?.Invoke(uiNotificationOptions); |
|||
|
|||
await Notify(title ?? _localizer["Success"], message, NotificationType.Success); |
|||
} |
|||
|
|||
public async Task Warn(string message, string title = null, Action<UiNotificationOptions> options = null) |
|||
{ |
|||
var uiNotificationOptions = CreateDefaultOptions(); |
|||
options?.Invoke(uiNotificationOptions); |
|||
|
|||
await Notify(title ?? _localizer["Warn"], message, NotificationType.Warning); |
|||
} |
|||
|
|||
public async Task Error(string message, string title = null, Action<UiNotificationOptions> options = null) |
|||
{ |
|||
var uiNotificationOptions = CreateDefaultOptions(); |
|||
options?.Invoke(uiNotificationOptions); |
|||
|
|||
await Notify(title ?? _localizer["Error"], message, NotificationType.Error); |
|||
} |
|||
|
|||
protected virtual async Task Notify(string title, string message, NotificationType notificationType) |
|||
{ |
|||
await NoticeService.Open(new NotificationConfig |
|||
{ |
|||
Message = title, |
|||
Description = message, |
|||
Placement = NotificationPlacement.BottomRight, |
|||
NotificationType = notificationType |
|||
}); |
|||
} |
|||
|
|||
protected virtual UiNotificationOptions CreateDefaultOptions() |
|||
{ |
|||
return new UiNotificationOptions(); |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.AspNetCore.Components.Progression; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Lsw.Abp.AntDesignUI; |
|||
|
|||
[Dependency(ReplaceServices = true)] |
|||
public class AntDesignUiPageProgressService: IUiPageProgressService, IScopedDependency |
|||
{ |
|||
public event EventHandler<UiPageProgressEventArgs> ProgressChanged; |
|||
|
|||
public Task Go(int? percentage, Action<UiPageProgressOptions> options = null) |
|||
{ |
|||
var uiPageProgressOptions = CreateDefaultOptions(); |
|||
options?.Invoke(uiPageProgressOptions); |
|||
|
|||
ProgressChanged?.Invoke(this, new UiPageProgressEventArgs(percentage, uiPageProgressOptions)); |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
|
|||
protected virtual UiPageProgressOptions CreateDefaultOptions() |
|||
{ |
|||
return new UiPageProgressOptions(); |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
namespace Lsw.Abp.AntDesignUI; |
|||
|
|||
public class BreadcrumbItem |
|||
{ |
|||
public string Text { get; set; } |
|||
|
|||
public object Icon { get; set; } |
|||
|
|||
public string Url { get; set; } |
|||
|
|||
public BreadcrumbItem(string text, string url = null, object icon = null) |
|||
{ |
|||
Text = text; |
|||
Url = url; |
|||
Icon = icon; |
|||
} |
|||
} |
|||
@ -0,0 +1,76 @@ |
|||
@typeparam TItem |
|||
|
|||
<Table TItem="TItem" DataSource="@Data" Loading="@Loading" OnChange="@OnChange" |
|||
@bind-PageIndex="@CurrentPage" |
|||
@bind-PageSize="@PageSize" |
|||
Total="TotalItems" |
|||
Class="@Class" |
|||
RemoteDataSource="true" |
|||
Responsive="@Responsive" |
|||
ScrollX="1500" |
|||
ScrollY="300"> |
|||
|
|||
@if (Columns != null) |
|||
{ |
|||
foreach (var column in Columns) |
|||
{ |
|||
if (column.Actions.Any()) |
|||
{ |
|||
<TableEntityActionsColumn TItem="TItem" @ref="ActionColumns[column.Title]" Title="@column.Title"> |
|||
<EntityActions TItem="TItem" EntityActionsColumn="ActionColumns[column.Title]"> |
|||
@foreach (var action in column.Actions) |
|||
{ |
|||
if (action.ConfirmationMessage != null) |
|||
{ |
|||
<EntityAction TItem="TItem" |
|||
Color="@(action.Color != null ? action.Color.ToString() : ButtonType.Primary)" |
|||
Icon="@action.Icon" |
|||
Clicked="async () => await action.Clicked(context)" |
|||
ConfirmationMessage="() => action.ConfirmationMessage.Invoke(context)" |
|||
Visible="@(action.Visible?.Invoke(context) ?? true)" |
|||
Text="@action.Text" |
|||
Disabled="@action.Disabled"> |
|||
</EntityAction> |
|||
} |
|||
else |
|||
{ |
|||
<EntityAction TItem="TItem" |
|||
Clicked="async () => await action.Clicked(context)" |
|||
Color="@(action.Color != null ? action.Color.ToString() : ButtonType.Default)" |
|||
Icon="@action.Icon" |
|||
Visible="@(action.Visible?.Invoke(context) ?? true)" |
|||
Text="@action.Text" |
|||
Disabled="@action.Disabled"> |
|||
</EntityAction> |
|||
} |
|||
} |
|||
</EntityActions> |
|||
</TableEntityActionsColumn> |
|||
} |
|||
else |
|||
{ |
|||
if (column.Component != null) |
|||
{ |
|||
<Column TData="object" Title="@column.Title"> |
|||
@RenderCustomTableColumnComponent(column.Component, context) |
|||
</Column> |
|||
} |
|||
else |
|||
{ |
|||
if (column.ValueConverter == null) |
|||
{ |
|||
<Column TData="object" Sortable="@column.Sortable" Title="@column.Title"> |
|||
@GetColumnValue(context, column.Data); |
|||
</Column> |
|||
} |
|||
else |
|||
{ |
|||
<Column TData="object" Sortable="@column.Sortable" Title="@column.Title"> |
|||
@(GetConvertedFieldValue(context, column)) |
|||
</Column> |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</Table> |
|||
@ -0,0 +1,72 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using AntDesign.TableModels; |
|||
using Microsoft.AspNetCore.Components; |
|||
using Microsoft.Extensions.Localization; |
|||
using Volo.Abp.AspNetCore.Components.Web.Extensibility.TableColumns; |
|||
|
|||
namespace Lsw.Abp.AntDesignUI.Components; |
|||
|
|||
public partial class AbpExtensibleDataGrid<TItem> : ComponentBase |
|||
{ |
|||
protected const string DataFieldAttributeName = "Data"; |
|||
|
|||
protected Dictionary<string, TableEntityActionsColumn<TItem>> ActionColumns = new(); |
|||
|
|||
[Parameter] |
|||
public IEnumerable<TItem> Data { get; set; } |
|||
|
|||
[Parameter] |
|||
public int? TotalItems { get; set; } |
|||
|
|||
[Parameter] |
|||
public int PageSize { get; set; } |
|||
|
|||
[Parameter] |
|||
public IEnumerable<TableColumn> Columns { get; set; } |
|||
|
|||
[Parameter] |
|||
public EventCallback<QueryModel<TItem>> OnChange { get; set; } |
|||
|
|||
[Parameter] |
|||
public int CurrentPage { get; set; } = 1; |
|||
|
|||
[Parameter] |
|||
public string Class { get; set; } |
|||
|
|||
[Parameter] |
|||
public bool Responsive { get; set; } |
|||
|
|||
[Parameter] |
|||
public bool Loading { get; set; } |
|||
|
|||
[Inject] |
|||
public IStringLocalizerFactory StringLocalizerFactory { get; set; } |
|||
|
|||
protected virtual RenderFragment RenderCustomTableColumnComponent(Type type, object data) |
|||
{ |
|||
return (builder) => |
|||
{ |
|||
builder.OpenComponent(0, type); |
|||
builder.AddAttribute(0, DataFieldAttributeName, data); |
|||
builder.CloseComponent(); |
|||
}; |
|||
} |
|||
|
|||
protected virtual object GetColumnValue(object data, string fieldName) |
|||
{ |
|||
return data.GetType().GetProperty(fieldName)?.GetValue(data); |
|||
} |
|||
|
|||
protected virtual string GetConvertedFieldValue(TItem item, TableColumn columnDefinition) |
|||
{ |
|||
var convertedValue = columnDefinition.ValueConverter.Invoke(item); |
|||
if (!columnDefinition.DisplayFormat.IsNullOrEmpty()) |
|||
{ |
|||
return string.Format(columnDefinition.DisplayFormatProvider, columnDefinition.DisplayFormat, |
|||
convertedValue); |
|||
} |
|||
|
|||
return convertedValue; |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
namespace Lsw.Abp.AntDesignUI.Components; |
|||
|
|||
public enum ActionType |
|||
{ |
|||
Dropdown, |
|||
Button |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
@typeparam TItem |
|||
|
|||
@if (Visible && HasPermission) |
|||
{ |
|||
if (ParentActions.Type == ActionType.Dropdown) |
|||
{ |
|||
if (!Primary) |
|||
{ |
|||
<MenuItem disabled="@Disabled"> |
|||
<a onclick="@ActionClickedAsync()">@Text</a> |
|||
</MenuItem> |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
<Button disabled="@Disabled" |
|||
Icon="@Icon" |
|||
Block="true" |
|||
Type="@Color" |
|||
onclick="@ActionClickedAsync()"> |
|||
@if (!string.IsNullOrEmpty(Icon)) |
|||
{ |
|||
<Icon Name="@Icon"/> |
|||
} |
|||
@Text |
|||
</Button> |
|||
} |
|||
} |
|||
@ -0,0 +1,76 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using AntDesign; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.AspNetCore.Components; |
|||
using Volo.Abp.AspNetCore.Components.Messages; |
|||
|
|||
namespace Lsw.Abp.AntDesignUI.Components; |
|||
|
|||
public partial class EntityAction<TItem> : ComponentBase |
|||
{ |
|||
internal bool HasPermission { get; set; } = true; |
|||
|
|||
[Parameter] |
|||
public bool Visible { get; set; } = true; |
|||
|
|||
[Parameter] |
|||
public bool Disabled { get; set; } = false; |
|||
|
|||
[Parameter] |
|||
public string Text { get; set; } |
|||
|
|||
[Parameter] |
|||
public string Icon { get; set; } |
|||
|
|||
[Parameter] |
|||
public string Color { get; set; } = ButtonType.Default; |
|||
|
|||
[Parameter] |
|||
public bool Primary { get; set; } |
|||
|
|||
[Parameter] |
|||
public EventCallback Clicked { get; set; } |
|||
|
|||
[Parameter] |
|||
public Func<string> ConfirmationMessage { get; set; } |
|||
|
|||
[Parameter] |
|||
public string RequiredPolicy { get; set; } |
|||
|
|||
[CascadingParameter] |
|||
public EntityActions<TItem> ParentActions { get; set; } |
|||
|
|||
[Inject] |
|||
protected IAuthorizationService AuthorizationService { get; set; } |
|||
|
|||
[Inject] |
|||
protected IUiMessageService UiMessageService { get; set; } |
|||
|
|||
protected override async Task OnInitializedAsync() |
|||
{ |
|||
await base.OnInitializedAsync(); |
|||
|
|||
if (!RequiredPolicy.IsNullOrEmpty()) |
|||
{ |
|||
HasPermission = await AuthorizationService.IsGrantedAsync(RequiredPolicy); |
|||
} |
|||
|
|||
ParentActions.AddAction(this); |
|||
} |
|||
|
|||
public virtual async Task ActionClickedAsync() |
|||
{ |
|||
if (ConfirmationMessage != null) |
|||
{ |
|||
if (await UiMessageService.Confirm(ConfirmationMessage())) |
|||
{ |
|||
await InvokeAsync(async () => await Clicked.InvokeAsync()); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
await Clicked.InvokeAsync(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
@typeparam TItem |
|||
|
|||
<CascadingValue Value="this" IsFixed="true"> |
|||
|
|||
@if (Type == ActionType.Dropdown) |
|||
{ |
|||
if (HasPrimaryAction) |
|||
{ |
|||
<DropdownButton OnClick="async () => await PrimaryAction.ActionClickedAsync()" Disabled="@Disabled" Type="@PrimaryAction.Color" Block="true"> |
|||
<Overlay> |
|||
<Menu> |
|||
@ChildContent |
|||
</Menu> |
|||
</Overlay> |
|||
<ChildContent> |
|||
@PrimaryAction.Text |
|||
</ChildContent> |
|||
</DropdownButton> |
|||
} |
|||
else |
|||
{ |
|||
<Dropdown> |
|||
<Overlay> |
|||
<Menu> |
|||
@ChildContent |
|||
</Menu> |
|||
</Overlay> |
|||
<ChildContent> |
|||
<Button Type="@ToggleColor">@ToggleText <Icon Type="down"/></Button> |
|||
</ChildContent> |
|||
</Dropdown> |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
@ChildContent |
|||
} |
|||
|
|||
</CascadingValue> |
|||
@ -0,0 +1,69 @@ |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using AntDesign; |
|||
using Localization.Resources.AbpUi; |
|||
using Microsoft.AspNetCore.Components; |
|||
using Microsoft.Extensions.Localization; |
|||
|
|||
namespace Lsw.Abp.AntDesignUI.Components; |
|||
|
|||
public partial class EntityActions<TItem> : ComponentBase |
|||
{ |
|||
protected readonly List<EntityAction<TItem>> Actions = new(); |
|||
|
|||
protected bool HasPrimaryAction => Actions.Any(t => t.Primary); |
|||
|
|||
protected EntityAction<TItem> PrimaryAction => Actions.FirstOrDefault(t => t.Primary); |
|||
|
|||
[Parameter] |
|||
public ActionType Type { get; set; } = ActionType.Dropdown; |
|||
|
|||
[Parameter] |
|||
public bool Disabled { get; set; } = false; |
|||
|
|||
[Parameter] |
|||
public string ToggleColor { get; set; } = ButtonType.Primary; |
|||
|
|||
[Parameter] |
|||
public string ToggleText { get; set; } |
|||
|
|||
[Parameter] |
|||
public RenderFragment ChildContent { get; set; } |
|||
|
|||
[Parameter] |
|||
public TableEntityActionsColumn<TItem> EntityActionsColumn { get; set; } |
|||
|
|||
[CascadingParameter] |
|||
public TableEntityActionsColumn<TItem> ParentEntityActionsColumn { get; set; } |
|||
|
|||
[Inject] |
|||
public IStringLocalizer<AbpUiResource> UiLocalizer { get; set; } |
|||
|
|||
protected override void OnInitialized() |
|||
{ |
|||
base.OnInitialized(); |
|||
ToggleText = UiLocalizer["Actions"]; |
|||
} |
|||
|
|||
protected override async Task OnAfterRenderAsync(bool firstRender) |
|||
{ |
|||
if (firstRender) |
|||
{ |
|||
if (ParentEntityActionsColumn != null) |
|||
{ |
|||
ParentEntityActionsColumn.Hidden = !Actions.Any(t => t.Visible && t.HasPermission); |
|||
} |
|||
|
|||
await InvokeAsync(StateHasChanged); |
|||
} |
|||
|
|||
await base.OnAfterRenderAsync(firstRender); |
|||
} |
|||
|
|||
internal void AddAction(EntityAction<TItem> action) |
|||
{ |
|||
Actions.Add(action); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,51 @@ |
|||
@using Volo.Abp.AspNetCore.Components.Alerts |
|||
@using System.Collections.Specialized |
|||
@using Microsoft.AspNetCore.Components.Routing |
|||
|
|||
@foreach (var message in _messages) |
|||
{ |
|||
<Alert Type="@message.Type.ToString().ToLower()" |
|||
Message="@message.Title" |
|||
Description="@message.Text" |
|||
ShowIcon="true" |
|||
Closable="@message.Dismissible"/> |
|||
} |
|||
|
|||
@code { |
|||
|
|||
private readonly List<AlertMessage> _messages = new(); |
|||
|
|||
[Inject] |
|||
protected IAlertManager AlertManager { get; set; } |
|||
|
|||
[Inject] |
|||
protected NavigationManager NavigationManager { get; set; } |
|||
|
|||
protected override void OnInitialized() |
|||
{ |
|||
base.OnInitialized(); |
|||
AlertManager.Alerts.CollectionChanged += Alerts_CollectionChanged; |
|||
NavigationManager.LocationChanged += NavigationManager_LocationChanged; |
|||
|
|||
_messages.AddRange(AlertManager.Alerts); |
|||
} |
|||
|
|||
private void NavigationManager_LocationChanged(object sender, LocationChangedEventArgs e) |
|||
{ |
|||
AlertManager.Alerts.Clear(); |
|||
_messages.Clear(); |
|||
} |
|||
|
|||
protected virtual void Alerts_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) |
|||
{ |
|||
if (e.Action == NotifyCollectionChangedAction.Add) |
|||
{ |
|||
foreach (var item in e.NewItems) |
|||
{ |
|||
_messages.Add((AlertMessage)item); |
|||
} |
|||
} |
|||
InvokeAsync(StateHasChanged); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
@typeparam TItem |
|||
@using Localization.Resources.AbpUi |
|||
@using Microsoft.Extensions.Localization |
|||
@inherits Column<TItem> |
|||
<CascadingValue Value="@this" IsFixed="true"> |
|||
@ChildContent |
|||
</CascadingValue> |
|||
|
|||
@code { |
|||
[Inject] |
|||
public IStringLocalizer<AbpUiResource> UiLocalizer { get; set; } |
|||
|
|||
protected override void OnInitialized() |
|||
{ |
|||
Title = UiLocalizer["Actions"]; |
|||
Sortable = false; |
|||
base.OnInitialized(); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
<Button Type="@Color" onclick="@Clicked" Disabled="@Disabled"> |
|||
@if (Icon != null) |
|||
{ |
|||
<Icon Type="@Icon" Class="me-1"></Icon> |
|||
} |
|||
@Text |
|||
</Button> |
|||
|
|||
@code { |
|||
|
|||
[Parameter] |
|||
public string Color { get; set; } = ButtonType.Default; |
|||
|
|||
[Parameter] |
|||
public object Icon { get; set; } |
|||
|
|||
[Parameter] |
|||
public string Text { get; set; } |
|||
|
|||
[Parameter] |
|||
public Func<Task> Clicked { get; set; } |
|||
|
|||
[Parameter] |
|||
public bool Disabled { get; set; } |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
@if (_percent is >= 0 and <= 100) |
|||
{ |
|||
if (_progressStatus == ProgressStatus.Active) |
|||
{ |
|||
<Progress StrokeColor="_gradients" Percent=_percent></Progress> |
|||
} |
|||
else |
|||
{ |
|||
<Progress Percent=_percent></Progress> |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,47 @@ |
|||
using System.Collections.Generic; |
|||
using AntDesign; |
|||
using Microsoft.AspNetCore.Components; |
|||
using Volo.Abp.AspNetCore.Components.Progression; |
|||
|
|||
namespace Lsw.Abp.AntDesignUI.Components; |
|||
|
|||
public partial class UiPageProgress : ComponentBase |
|||
{ |
|||
private int? _percent; |
|||
|
|||
private ProgressStatus _progressStatus; |
|||
|
|||
private Dictionary<string, string> _gradients = new() |
|||
{ |
|||
{ "0%", "#108ee9" }, |
|||
{ "100%", "#87d068" } |
|||
}; |
|||
|
|||
[Inject] |
|||
protected IUiPageProgressService UiPageProgressService { get; set; } |
|||
|
|||
protected override void OnInitialized() |
|||
{ |
|||
base.OnInitialized(); |
|||
UiPageProgressService.ProgressChanged += OnProgressChanged; |
|||
} |
|||
|
|||
protected virtual void OnProgressChanged(object sender, UiPageProgressEventArgs e) |
|||
{ |
|||
_percent = e.Percentage; |
|||
SetProgressStatus(e.Options.Type); |
|||
} |
|||
|
|||
protected virtual void SetProgressStatus(UiPageProgressType pageProgressType) |
|||
{ |
|||
_progressStatus = pageProgressType switch |
|||
{ |
|||
UiPageProgressType.Info => ProgressStatus.Active, |
|||
UiPageProgressType.Default => ProgressStatus.Active, |
|||
UiPageProgressType.Success => ProgressStatus.Success, |
|||
UiPageProgressType.Warning => ProgressStatus.Normal, |
|||
UiPageProgressType.Error => ProgressStatus.Exception, |
|||
_ => _progressStatus |
|||
}; |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,16 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk.Razor"> |
|||
|
|||
<Import Project="..\..\configureawait.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net6.0</TargetFramework> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="AntDesign" Version="0.10.3.1" /> |
|||
<PackageReference Include="Volo.Abp.AspNetCore.Components.Web" Version="5.1.3" /> |
|||
<PackageReference Include="Volo.Abp.Authorization" Version="5.1.3" /> |
|||
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="5.1.3" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,2 @@ |
|||
@using Microsoft.AspNetCore.Components.Web |
|||
@using AntDesign |
|||
Loading…
Reference in new issue