Browse Source

Merge branch 'dev' of https://github.com/abpframework/abp into refactor/nav-items

pull/4404/head
mehmet-erim 6 years ago
parent
commit
354f742d60
  1. 2
      docs/en/Blob-Storing.md
  2. 2
      docs/en/Repositories.md
  3. 133
      docs/zh-Hans/Repositories.md
  4. 3
      docs/zh-Hans/SignalR-Integration.md
  5. 2
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/DefaultContainer.cs
  6. 15
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/AbpDistributedEntityEventOptions.cs
  7. 12
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/AutoEntityDistributedEventSelectorList.cs
  8. 78
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/AutoEntityDistributedEventSelectorListExtensions.cs
  9. 6
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityToEtoMapper.cs
  10. 3
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EtoMappingDictionary.cs
  11. 2
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EtoMappingDictionaryItem.cs
  12. 9
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/IAutoEntityDistributedEventSelectorList.cs
  13. 74
      framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeEventHelper.cs
  14. 2
      framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpDistributedEventBusOptions.cs
  15. 5
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/TestAppModule.cs
  16. 4
      modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/BloggingDomainModule.cs
  17. 22
      modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/GetAllInput.cs
  18. 12
      modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/en.json
  19. 36
      modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs
  20. 219
      modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/Index.cshtml
  21. 3
      modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/Index.cshtml.cs
  22. 3
      modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/index.css
  23. 71
      modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/index.js
  24. 1
      modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/index.min.css
  25. 6
      modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/index.scss
  26. 8
      modules/docs/src/Volo.Docs.Admin.Web/Volo.Docs.Admin.Web.csproj
  27. 6
      modules/docs/src/Volo.Docs.Admin.Web/compilerconfig.json
  28. 63
      modules/docs/src/Volo.Docs.Admin.Web/compilerconfig.json.defaults
  29. 4
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainModule.cs
  30. 23
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentRepository.cs
  31. 103
      modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Documents/EFCoreDocumentRepository.cs
  32. 124
      modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs
  33. 4
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityDomainModule.cs
  34. 9
      modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/AbpIdentityDomainTestModule.cs
  35. 15
      modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/Distributed_User_Change_Event_Tests.cs
  36. 4
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs
  37. 4
      modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/AbpTenantManagementDomainModule.cs
  38. 7
      npm/ng-packs/packages/core/src/lib/services/list.service.ts
  39. 13
      npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts
  40. 1
      samples/MicroserviceDemo/applications/BackendAdminApp.Host/BackendAdminAppHostModule.cs
  41. 6
      samples/MicroserviceDemo/microservices/IdentityService.Host/IdentityServiceHostModule.cs

2
docs/en/Blob-Storing.md

@ -169,7 +169,7 @@ public class ProfileAppService : ApplicationService
If you don't use the generic argument and directly inject the `IBlobContainer` (as explained before), you get the default container. Another way of injecting the default container is using `IBlobContainer<DefaultContainer>`, which returns exactly the same container. If you don't use the generic argument and directly inject the `IBlobContainer` (as explained before), you get the default container. Another way of injecting the default container is using `IBlobContainer<DefaultContainer>`, which returns exactly the same container.
The name of the default container is `Default`. The name of the default container is `default`.
### Named Containers ### Named Containers

2
docs/en/Repositories.md

@ -126,7 +126,7 @@ You can directly access the data access provider (`DbContext` in this case) to p
`IRepository` inherits from `IQueryable`, that means you can **directly use LINQ extension methods** on it, as shown in the example of the "*Generic Repositories*" section above. `IRepository` inherits from `IQueryable`, that means you can **directly use LINQ extension methods** on it, as shown in the example of the "*Generic Repositories*" section above.
**Example: Using the `Where(...)` &and the `ToList()` extension methods** **Example: Using the `Where(...)` and the `ToList()` extension methods**
````csharp ````csharp
var people = _personRepository var people = _personRepository

133
docs/zh-Hans/Repositories.md

@ -38,6 +38,8 @@ public class PersonAppService : ApplicationService
} }
```` ````
> 参阅 "*IQueryable & 异步操作*" 部分了解如何使用 **异步扩展方法**, 如 `ToListAsync()` (建议始终使用异步) 而不是 `ToList()`.
在这个例子中; 在这个例子中;
* `PersonAppService` 在它的构造函数中注入了 `IRepository<Person, Guid>` . * `PersonAppService` 在它的构造函数中注入了 `IRepository<Person, Guid>` .
@ -119,4 +121,133 @@ public class PersonRepository : EfCoreRepository<MyDbContext, Person, Guid>, IPe
} }
```` ````
你可以直接使用数据库访问提供程序 (本例中是 `DbContext` ) 来执行操作. 有关基于EF Core的自定义仓储的更多信息, 请参阅[EF Core 集成文档](Entity-Framework-Core.md). 你可以直接使用数据库访问提供程序 (本例中是 `DbContext` ) 来执行操作.
> 请参阅[EF Core](Entity-Framework-Core.md)或[MongoDb](MongoDB.md)了解如何自定义仓储.
## IQueryable & 异步操作
`IRepository` 继承自 `IQueryable`,这意味着你可以**直接使用LINQ扩展方法**. 如上面的*泛型仓储*示例.
**示例: 使用 `Where(...)` 和 `ToList()` 扩展方法**
````csharp
var people = _personRepository
.Where(p => p.Name.Contains(nameFilter))
.ToList();
````
`.ToList`, `Count()`... 是在 `System.Linq` 命名空间下定义的扩展方法. ([参阅所有方法](https://docs.microsoft.com/en-us/dotnet/api/system.linq.queryable)).
你通常想要使用 `.ToListAsync()`, `.CountAsync()`.... 来编写**真正的异步代码**.
但在你使用标准的[应用程序启动模板](Startup-Templates/Application.md)时会发现无法在应用层或领域层使用这些异步扩展方法,因为:
* 这里异步方法**不是标准LINQ方法**,它们定义在[Microsoft.EntityFrameworkCore](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore)Nuget包中.
* 标准模板应用层与领域层**不引用**EF Core 包以实现数据库提供程序独立.
根据你的需求和开发模式,你可以根据以下选项使用异步方法.s
> 强烈建议使用异步方法! 在执行数据库查询时不要使用同步LINQ方法,以便能够开发可伸缩的应用程序.
### 选项-1: 引用EF Core
最简单的方法是在你想要使用异步方法的项目直接引用EF Core包.
> 添加[Volo.Abp.EntityFrameworkCore](https://www.nuget.org/packages/Volo.Abp.EntityFrameworkCore)NuGet包到你的项目间接引用EF Core包. 这可以确保你的应用程序其余部分兼容正确版本的EF Core.
当你添加NuGet包后,你可以使用全功能的EF Core扩展方法.
**示例: 直接使用 `ToListAsync()`**
````csharp
var people = _personRepository
.Where(p => p.Name.Contains(nameFilter))
.ToListAsync();
````
此方法建议;
* 如果你正在开发一个应用程序并且**不打算在将来** 更新FE Core,或者如果以后需要更改,你可以**容忍**它. 如果你正在开发最终的应用程序,这是合理的.
#### MongoDB
如果使用的是MongoDB,则需要将[Volo.Abp.MongoDB] NuGet包添加到项目中. 但在这种情况下你也不能直接使用异步LINQ扩展(例如`ToListAsync`),因为MongoDB不提供 `IQueryable<T>`的异步扩展方法,而是提供 `IMongoQueryable<T>`. 你需要先将查询强制转换为 `IMongoQueryable<T>` 才能使用异步扩展方法.
**示例: 转换Cast `IQueryable<T>` 为 `IMongoQueryable<T>` 并且使用 `ToListAsync()`**
````csharp
var people = ((IMongoQueryable<Person>)_personRepository
.Where(p => p.Name.Contains(nameFilter)))
.ToListAsync();
````
### 选项-2: 自定义仓储方法
你始终可以创建自定义仓储方法并使用特定数据库提供程序的API,比如这里的异步扩展方法. 有关自定义存储库的更多信息,请参阅[EF Core](Entity-Framework-Core.md)或[MongoDb](MongoDB.md)文档.
此方法建议;
* 如果你想**完全隔离**你的领域和应用层和数据库提供程序.
* 如果你开发可**重用的[应用模块](Modules/Index.md)**,并且不想强制使用特定的数据库提供程序,这应该作为一种[最佳实践](Best-Practices/Index.md).
### 选项-3: IAsyncQueryableExecuter
> 注意,此功能在ABP框架3.0以之后的版本可用,虽然它也可以用于较早的版本,但它提供的方法非常有限.
`IAsyncQueryableExecuter` 是一个用于异步执行 `IQueryable<T>` 对象的服务,**不依赖于实际的数据库提供程序**.
**示例: 注入并使用 `IAsyncQueryableExecuter.ToListAsync()` 方法**
````csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Linq;
namespace AbpDemo
{
public class ProductAppService : ApplicationService, IProductAppService
{
private readonly IRepository<Product, Guid> _productRepository;
private readonly IAsyncQueryableExecuter _asyncExecuter;
public ProductAppService(
IRepository<Product, Guid> productRepository,
IAsyncQueryableExecuter asyncExecuter)
{
_productRepository = productRepository;
_asyncExecuter = asyncExecuter;
}
public async Task<ListResultDto<ProductDto>> GetListAsync(string name)
{
//Create the query
var query = _productRepository
.Where(p => p.Name.Contains(name))
.OrderBy(p => p.Name);
//Run the query asynchronously
List<Product> products = await _asyncExecuter.ToListAsync(query);
//...
}
}
}
````
> `ApplicationService` 和 `DomainService` 基类已经预属性注入了 `AsyncExecuter` 属性,所以你可直接使用.
ABP框架使用实际数据库提供程序的API异步执行查询.虽然这不是执行查询的常见方式,但它是使用异步API而不依赖于数据库提供者的最佳方式.
此方法建议;
* 如果你正在构建一个没有数据库提供程序集成包的**可重用库**,但是在某些情况下需要执行 `IQueryable<T>`对象.
For example, ABP Framework uses the `IAsyncQueryableExecuter` in the `CrudAppService` base class (see the [application services](Application-Services.md) document).
例如,ABP框架在 `CrudAppService` 基类中(参阅[应用程序](Application-Services.md)文档)使用 `IAsyncQueryableExecuter`.

3
docs/zh-Hans/SignalR-Integration.md

@ -234,4 +234,5 @@ ABP框架不会更改SignalR. 就像在其他ASP.NET Core应用程序中一样,
## 另请参阅 ## 另请参阅
* [微软SignalR文档](https://docs.microsoft.com/zh-cn/aspnet/core/signalr/introduction) * [微软SignalR文档](https://docs.microsoft.com/zh-cn/aspnet/core/signalr/introduction)
* [使用ABP,SignalR和RabbitMQ在分布式体系结构中的实时消息传递](https://volosoft.com/blog/RealTime-Messaging-Distributed-Architecture-Abp-SingalR-RabbitMQ)

2
framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/DefaultContainer.cs

@ -3,6 +3,6 @@
[BlobContainerName(Name)] [BlobContainerName(Name)]
public class DefaultContainer public class DefaultContainer
{ {
public const string Name = "Default"; public const string Name = "default";
} }
} }

15
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/AbpDistributedEntityEventOptions.cs

@ -0,0 +1,15 @@
namespace Volo.Abp.Domain.Entities.Events.Distributed
{
public class AbpDistributedEntityEventOptions
{
public IAutoEntityDistributedEventSelectorList AutoEventSelectors { get; }
public EtoMappingDictionary EtoMappings { get; set; }
public AbpDistributedEntityEventOptions()
{
AutoEventSelectors = new AutoEntityDistributedEventSelectorList();
EtoMappings = new EtoMappingDictionary();
}
}
}

12
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/AutoEntityDistributedEventSelectorList.cs

@ -0,0 +1,12 @@
using System.Collections.Generic;
namespace Volo.Abp.Domain.Entities.Events.Distributed
{
public class AutoEntityDistributedEventSelectorList : List<NamedTypeSelector>, IAutoEntityDistributedEventSelectorList
{
public bool RemoveByName(string name)
{
return RemoveAll(s => s.Name == name) > 0;
}
}
}

78
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/AutoEntityDistributedEventSelectorListExtensions.cs

@ -0,0 +1,78 @@
using System;
using System.Linq;
using JetBrains.Annotations;
namespace Volo.Abp.Domain.Entities.Events.Distributed
{
public static class AutoEntityDistributedEventSelectorListExtensions
{
public const string AllEntitiesSelectorName = "All";
public static void AddNamespace([NotNull] this IAutoEntityDistributedEventSelectorList selectors, [NotNull] string namespaceName)
{
Check.NotNull(selectors, nameof(selectors));
var selectorName = "Namespace:" + namespaceName;
if (selectors.Any(s => s.Name == selectorName))
{
return;
}
selectors.Add(
new NamedTypeSelector(
selectorName,
t => t.FullName?.StartsWith(namespaceName) ?? false
)
);
}
/// <summary>
/// Adds a specific entity type and the types derived from that entity type.
/// </summary>
/// <typeparam name="TEntity">Type of the entity</typeparam>
public static void Add<TEntity>([NotNull] this IAutoEntityDistributedEventSelectorList selectors)
where TEntity : IEntity
{
Check.NotNull(selectors, nameof(selectors));
var selectorName = "Entity:" + typeof(TEntity).FullName;
if (selectors.Any(s => s.Name == selectorName))
{
return;
}
selectors.Add(
new NamedTypeSelector(
selectorName,
t => typeof(TEntity).IsAssignableFrom(t)
)
);
}
/// <summary>
/// Adds all entity types.
/// </summary>
public static void AddAll([NotNull] this IAutoEntityDistributedEventSelectorList selectors)
{
Check.NotNull(selectors, nameof(selectors));
if (selectors.Any(s => s.Name == AllEntitiesSelectorName))
{
return;
}
selectors.Add(
new NamedTypeSelector(
AllEntitiesSelectorName,
t => typeof(IEntity).IsAssignableFrom(t)
)
);
}
public static bool IsMatch([NotNull] this IAutoEntityDistributedEventSelectorList selectors, Type entityType)
{
Check.NotNull(selectors, nameof(selectors));
return selectors.Any(s => s.Predicate(entityType));
}
}
}

6
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EntityToEtoMapper.cs

@ -3,7 +3,6 @@ using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.DynamicProxy; using Volo.Abp.DynamicProxy;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.ObjectMapping; using Volo.Abp.ObjectMapping;
namespace Volo.Abp.Domain.Entities.Events.Distributed namespace Volo.Abp.Domain.Entities.Events.Distributed
@ -11,10 +10,11 @@ namespace Volo.Abp.Domain.Entities.Events.Distributed
public class EntityToEtoMapper : IEntityToEtoMapper, ITransientDependency public class EntityToEtoMapper : IEntityToEtoMapper, ITransientDependency
{ {
protected IHybridServiceScopeFactory HybridServiceScopeFactory { get; } protected IHybridServiceScopeFactory HybridServiceScopeFactory { get; }
protected AbpDistributedEventBusOptions Options { get; }
protected AbpDistributedEntityEventOptions Options { get; }
public EntityToEtoMapper( public EntityToEtoMapper(
IOptions<AbpDistributedEventBusOptions> options, IOptions<AbpDistributedEntityEventOptions> options,
IHybridServiceScopeFactory hybridServiceScopeFactory) IHybridServiceScopeFactory hybridServiceScopeFactory)
{ {
HybridServiceScopeFactory = hybridServiceScopeFactory; HybridServiceScopeFactory = hybridServiceScopeFactory;

3
framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/EtoMappingDictionary.cs → framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EtoMappingDictionary.cs

@ -1,7 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Volo.Abp.EventBus.Distributed;
namespace Volo.Abp.EventBus.Distributed namespace Volo.Abp.Domain.Entities.Events.Distributed
{ {
public class EtoMappingDictionary : Dictionary<Type, EtoMappingDictionaryItem> public class EtoMappingDictionary : Dictionary<Type, EtoMappingDictionaryItem>
{ {

2
framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/EtoMappingDictionaryItem.cs → framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/EtoMappingDictionaryItem.cs

@ -1,6 +1,6 @@
using System; using System;
namespace Volo.Abp.EventBus.Distributed namespace Volo.Abp.Domain.Entities.Events.Distributed
{ {
public class EtoMappingDictionaryItem public class EtoMappingDictionaryItem
{ {

9
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/Distributed/IAutoEntityDistributedEventSelectorList.cs

@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace Volo.Abp.Domain.Entities.Events.Distributed
{
public interface IAutoEntityDistributedEventSelectorList : IList<NamedTypeSelector>
{
bool RemoveByName(string name);
}
}

74
framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Events/EntityChangeEventHelper.cs

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities.Events.Distributed; using Volo.Abp.Domain.Entities.Events.Distributed;
@ -22,13 +23,16 @@ namespace Volo.Abp.Domain.Entities.Events
protected IUnitOfWorkManager UnitOfWorkManager { get; } protected IUnitOfWorkManager UnitOfWorkManager { get; }
protected IEntityToEtoMapper EntityToEtoMapper { get; } protected IEntityToEtoMapper EntityToEtoMapper { get; }
protected AbpDistributedEntityEventOptions DistributedEntityEventOptions { get; }
public EntityChangeEventHelper( public EntityChangeEventHelper(
IUnitOfWorkManager unitOfWorkManager, IUnitOfWorkManager unitOfWorkManager,
IEntityToEtoMapper entityToEtoMapper) IEntityToEtoMapper entityToEtoMapper,
IOptions<AbpDistributedEntityEventOptions> distributedEntityEventOptions)
{ {
UnitOfWorkManager = unitOfWorkManager; UnitOfWorkManager = unitOfWorkManager;
EntityToEtoMapper = entityToEtoMapper; EntityToEtoMapper = entityToEtoMapper;
DistributedEntityEventOptions = distributedEntityEventOptions.Value;
LocalEventBus = NullLocalEventBus.Instance; LocalEventBus = NullLocalEventBus.Instance;
DistributedEventBus = NullDistributedEventBus.Instance; DistributedEventBus = NullDistributedEventBus.Instance;
@ -65,18 +69,32 @@ namespace Volo.Abp.Domain.Entities.Events
false false
); );
var eto = EntityToEtoMapper.Map(entity); if (ShouldPublishDistributedEventForEntity(entity))
if (eto != null)
{ {
await TriggerEventWithEntity( var eto = EntityToEtoMapper.Map(entity);
DistributedEventBus, if (eto != null)
typeof(EntityCreatedEto<>), {
eto, await TriggerEventWithEntity(
false DistributedEventBus,
); typeof(EntityCreatedEto<>),
eto,
false
);
}
} }
} }
private bool ShouldPublishDistributedEventForEntity(object entity)
{
return DistributedEntityEventOptions
.AutoEventSelectors
.IsMatch(
ProxyHelper
.UnProxy(entity)
.GetType()
);
}
public virtual async Task TriggerEntityUpdatingEventAsync(object entity) public virtual async Task TriggerEntityUpdatingEventAsync(object entity)
{ {
await TriggerEventWithEntity( await TriggerEventWithEntity(
@ -96,15 +114,18 @@ namespace Volo.Abp.Domain.Entities.Events
false false
); );
var eto = EntityToEtoMapper.Map(entity); if (ShouldPublishDistributedEventForEntity(entity))
if (eto != null)
{ {
await TriggerEventWithEntity( var eto = EntityToEtoMapper.Map(entity);
DistributedEventBus, if (eto != null)
typeof(EntityUpdatedEto<>), {
eto, await TriggerEventWithEntity(
false DistributedEventBus,
); typeof(EntityUpdatedEto<>),
eto,
false
);
}
} }
} }
@ -127,15 +148,18 @@ namespace Volo.Abp.Domain.Entities.Events
false false
); );
var eto = EntityToEtoMapper.Map(entity); if (ShouldPublishDistributedEventForEntity(entity))
if (eto != null)
{ {
await TriggerEventWithEntity( var eto = EntityToEtoMapper.Map(entity);
DistributedEventBus, if (eto != null)
typeof(EntityDeletedEto<>), {
EntityToEtoMapper.Map(entity), await TriggerEventWithEntity(
false DistributedEventBus,
); typeof(EntityDeletedEto<>),
eto,
false
);
}
} }
} }

2
framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Distributed/AbpDistributedEventBusOptions.cs

@ -5,12 +5,10 @@ namespace Volo.Abp.EventBus.Distributed
public class AbpDistributedEventBusOptions public class AbpDistributedEventBusOptions
{ {
public ITypeList<IEventHandler> Handlers { get; } public ITypeList<IEventHandler> Handlers { get; }
public EtoMappingDictionary EtoMappings { get; set; }
public AbpDistributedEventBusOptions() public AbpDistributedEventBusOptions()
{ {
Handlers = new TypeList<IEventHandler>(); Handlers = new TypeList<IEventHandler>();
EtoMappings = new EtoMappingDictionary();
} }
} }
} }

5
framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/TestAppModule.cs

@ -4,7 +4,7 @@ using Volo.Abp.Autofac;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.TestApp.Domain; using Volo.Abp.TestApp.Domain;
using Volo.Abp.AutoMapper; using Volo.Abp.AutoMapper;
using Volo.Abp.EventBus.Distributed; using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.TestApp.Application.Dto; using Volo.Abp.TestApp.Application.Dto;
using Volo.Abp.Threading; using Volo.Abp.Threading;
@ -45,8 +45,9 @@ namespace Volo.Abp.TestApp
private void ConfigureDistributedEventBus() private void ConfigureDistributedEventBus()
{ {
Configure<AbpDistributedEventBusOptions>(options => Configure<AbpDistributedEntityEventOptions>(options =>
{ {
options.AutoEventSelectors.Add<Person>();
options.EtoMappings.Add<Person, PersonEto>(); options.EtoMappings.Add<Person, PersonEto>();
}); });
} }

4
modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/BloggingDomainModule.cs

@ -1,7 +1,7 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AutoMapper; using Volo.Abp.AutoMapper;
using Volo.Abp.Domain; using Volo.Abp.Domain;
using Volo.Abp.EventBus.Distributed; using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Blogging.Blogs; using Volo.Blogging.Blogs;
using Volo.Blogging.Comments; using Volo.Blogging.Comments;
@ -25,7 +25,7 @@ namespace Volo.Blogging
options.AddProfile<BloggingDomainMappingProfile>(validate: true); options.AddProfile<BloggingDomainMappingProfile>(validate: true);
}); });
Configure<AbpDistributedEventBusOptions>(options => Configure<AbpDistributedEntityEventOptions>(options =>
{ {
options.EtoMappings.Add<Blog, BlogEto>(typeof(BloggingDomainModule)); options.EtoMappings.Add<Blog, BlogEto>(typeof(BloggingDomainModule));
options.EtoMappings.Add<Comment, CommentEto>(typeof(BloggingDomainModule)); options.EtoMappings.Add<Comment, CommentEto>(typeof(BloggingDomainModule));

22
modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/GetAllInput.cs

@ -12,10 +12,28 @@ namespace Volo.Docs.Admin.Documents
[StringLength(DocumentConsts.MaxNameLength)] [StringLength(DocumentConsts.MaxNameLength)]
public string Name { get; set; } public string Name { get; set; }
[StringLength(DocumentConsts.MaxVersionNameLength)]
public string Version { get; set; }
[StringLength(DocumentConsts.MaxLanguageCodeNameLength)] [StringLength(DocumentConsts.MaxLanguageCodeNameLength)]
public string LanguageCode { get; set; } public string LanguageCode { get; set; }
[StringLength(DocumentConsts.MaxVersionNameLength)] [StringLength(DocumentConsts.MaxFileNameNameLength)]
public string Version { get; set; } public string FileName { get; set; }
[StringLength(DocumentConsts.MaxFormatNameLength)]
public string Format { get; set; }
public DateTime? CreationTimeMin { get; set; }
public DateTime? CreationTimeMax { get; set; }
public DateTime? LastUpdatedTimeMin { get; set; }
public DateTime? LastUpdatedTimeMax { get; set; }
public DateTime? LastSignificantUpdateTimeMin { get; set; }
public DateTime? LastSignificantUpdateTimeMax { get; set; }
public DateTime? LastCachedTimeMin { get; set; }
public DateTime? LastCachedTimeMax { get; set; }
} }
} }

12
modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/en.json

@ -43,6 +43,16 @@
"ReIndexDocumentConfirmation": "Are you sure you want to reindex this item?", "ReIndexDocumentConfirmation": "Are you sure you want to reindex this item?",
"DeleteDocumentFromDbConfirmation": "Are you sure you want to delete this item from database?", "DeleteDocumentFromDbConfirmation": "Are you sure you want to delete this item from database?",
"DeleteFromDatabase": "Delete from database", "DeleteFromDatabase": "Delete from database",
"Deleted": "Deleted" "Deleted": "Deleted",
"Search": "Search",
"StartDate": "Start date",
"EndDate": "End date",
"CreationTime": "Creation time",
"LastUpdateTime": "Last update",
"LastSignificantUpdateTime": "Last significant update",
"Version": "Version",
"LanguageCode": "Language code",
"FileName": "File name",
"LastCachedTime": "Cache time"
} }
} }

36
modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs

@ -137,20 +137,40 @@ namespace Volo.Docs.Admin.Documents
public async Task<PagedResultDto<DocumentDto>> GetAllAsync(GetAllInput input) public async Task<PagedResultDto<DocumentDto>> GetAllAsync(GetAllInput input)
{ {
var totalCount = await _documentRepository.GetAllCountAsync( var totalCount = await _documentRepository.GetAllCountAsync(
projectId: input.ProjectId, projectId: input.ProjectId,
name: input.Name, name: input.Name,
version: input.Version, version: input.Version,
languageCode: input.LanguageCode, languageCode: input.LanguageCode,
sorting: input.Sorting, fileName: input.FileName,
maxResultCount: input.MaxResultCount, format: input.Format,
skipCount: input.SkipCount creationTimeMin: input.CreationTimeMin,
); creationTimeMax: input.CreationTimeMax,
lastUpdatedTimeMin: input.LastUpdatedTimeMin,
lastUpdatedTimeMax: input.LastUpdatedTimeMax,
lastSignificantUpdateTimeMin: input.LastSignificantUpdateTimeMin,
lastSignificantUpdateTimeMax: input.LastSignificantUpdateTimeMax,
lastCachedTimeMin: input.LastCachedTimeMin,
lastCachedTimeMax: input.LastCachedTimeMax,
sorting: input.Sorting,
maxResultCount: input.MaxResultCount,
skipCount: input.SkipCount
);
var docs = await _documentRepository.GetAllAsync( var docs = await _documentRepository.GetAllAsync(
projectId: input.ProjectId, projectId: input.ProjectId,
name: input.Name, name: input.Name,
version: input.Version, version: input.Version,
languageCode: input.LanguageCode, languageCode: input.LanguageCode,
fileName: input.FileName,
format: input.Format,
creationTimeMin: input.CreationTimeMin,
creationTimeMax: input.CreationTimeMax,
lastUpdatedTimeMin: input.LastUpdatedTimeMin,
lastUpdatedTimeMax: input.LastUpdatedTimeMax,
lastSignificantUpdateTimeMin: input.LastSignificantUpdateTimeMin,
lastSignificantUpdateTimeMax: input.LastSignificantUpdateTimeMax,
lastCachedTimeMin: input.LastCachedTimeMin,
lastCachedTimeMax: input.LastCachedTimeMax,
sorting: input.Sorting, sorting: input.Sorting,
maxResultCount: input.MaxResultCount, maxResultCount: input.MaxResultCount,
skipCount: input.SkipCount skipCount: input.SkipCount

219
modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/Index.cshtml

@ -22,31 +22,194 @@
<abp-script src="/Pages/Docs/Admin/Documents/index.js" /> <abp-script src="/Pages/Docs/Admin/Documents/index.js" />
} }
<abp-card> @section styles {
<abp-card-header> <abp-style src="/Pages/Docs/Admin/Documents/index.min.css" />
<abp-row> }
<h2>Filters ...</h2>
@*<abp-column size-md="_6" class="text-right"> <div id="DocumentsContainer">
<abp-button button-type="Primary" icon="plus" text="@L["ReIndexAllProjects"].Value" id="ReIndexAllProjects" /> <abp-card>
</abp-column>*@ <abp-card-header>
</abp-row> <form class="form-inline" autocomplete="off" id="FilterForm">
</abp-card-header>
<abp-card-body> <div class="form-row">
<abp-table striped-rows="true" id="DocumentsTable" class="nowrap"> <div class="col-auto">
<thead> <div class="input-group mb-2">
<tr> <div class="input-group-prepend">
<th>@L["Actions"]</th> <div class="input-group-text">@L["Name"].Value</div>
<th>@L["Name"]</th> </div>
<th>@L["Version"]</th>
<th>@L["LanguageCode"]</th> <input type="text"
<th>@L["FileName"]</th> id="Name"
<th>@L["Format"]</th> name="Name"
<th>@L["CreationTime"]</th> class="form-control mr-sm-2">
<th>@L["LastUpdatedTime"]</th> </div>
<th>@L["LastSignificantUpdateTime"]</th> </div>
<th>@L["LastCachedTime"]</th>
</tr> <div class="col-auto">
</thead> <div class="input-group mb-2">
</abp-table> <div class="input-group-prepend">
</abp-card-body> <div class="input-group-text">@L["Version"].Value</div>
</abp-card> </div>
<input type="text"
id="Version"
name="Version"
class="form-control mr-sm-2">
</div>
</div>
<div class="col-auto">
<div class="input-group mb-2">
<div class="input-group-prepend">
<div class="input-group-text">@L["LanguageCode"].Value</div>
</div>
<input type="text"
id="LanguageCode"
name="LanguageCode"
class="form-control mr-sm-2">
</div>
</div>
<div class="col-auto">
<div class="input-group mb-2">
<div class="input-group-prepend">
<div class="input-group-text">@L["FileName"].Value</div>
</div>
<input type="text"
id="FileName"
name="FileName"
class="form-control mr-sm-2">
</div>
</div>
<div class="col-auto">
<div class="input-group mb-2">
<div class="input-group-prepend">
<div class="input-group-text">@L["Format"].Value</div>
</div>
<input type="text"
id="Format"
name="Format"
class="form-control mr-sm-2">
</div>
</div>
<div class="col-auto">
<div class="input-group mb-2">
<div class="input-group-prepend">
<div class="input-group-text">@L["CreationTime"].Value</div>
</div>
<span>
<input type="date"
id="CreationTimeMin"
name="CreationTimeMin"
class="form-control datepicker"
placeholder="@L["StartDate"]">
<span>-</span>
<input type="date"
id="CreationTimeMax"
name="CreationTimeMax"
placeholder="@L["EndDate"]"
class="form-control datepicker">
</span>
</div>
</div>
<div class="col-auto">
<div class="input-group mb-2">
<div class="input-group-prepend">
<div class="input-group-text">@L["LastUpdateTime"].Value</div>
</div>
<span>
<input type="date"
id="LastUpdatedTimeMin"
name="LastUpdatedTimeMin"
class="form-control datepicker"
placeholder="@L["StartDate"]">
<span>-</span>
<input type="date"
id="LastUpdatedTimeMax"
name="LastUpdatedTimeMax"
placeholder="@L["EndDate"]"
class="form-control datepicker">
</span>
</div>
</div>
<div class="col-auto">
<div class="input-group mb-2">
<div class="input-group-prepend">
<div class="input-group-text">@L["LastSignificantUpdateTime"].Value</div>
</div>
<span>
<input type="date"
id="LastSignificantUpdateTimeMin"
name="LastSignificantUpdateTimeMin"
class="form-control datepicker"
placeholder="@L["StartDate"]">
<span>-</span>
<input type="date"
id="LastSignificantUpdateTimeMax"
name="LastSignificantUpdateTimeMax"
placeholder="@L["EndDate"]"
class="form-control datepicker">
</span>
</div>
</div>
<div class="col-auto">
<div class="input-group mb-2">
<div class="input-group-prepend">
<div class="input-group-text">@L["LastCachedTime"].Value</div>
</div>
<span>
<input type="date"
id="LastCachedTimeMin"
name="LastCachedTimeMin"
class="form-control datepicker"
placeholder="@L["StartDate"]">
<span>-</span>
<input type="date"
id="LastCachedTimeMax"
name="LastCachedTimeMax"
placeholder="@L["EndDate"]"
class="form-control datepicker">
</span>
</div>
</div>
<div class="col-auto">
<abp-button button-type="Primary" icon="search" id="SearchButton" style="line-height: 25px;" text="@L["Search"].Value"></abp-button>
</div>
</div>
</form>
</abp-card-header>
<abp-card-body>
<abp-table striped-rows="true" id="DocumentsTable" class="nowrap">
<thead>
<tr>
<th>@L["Actions"]</th>
<th>@L["Name"]</th>
<th>@L["Version"]</th>
<th>@L["LanguageCode"]</th>
<th>@L["FileName"]</th>
<th>@L["Format"]</th>
<th>@L["CreationTime"]</th>
<th>@L["LastUpdatedTime"]</th>
<th>@L["LastSignificantUpdateTime"]</th>
<th>@L["LastCachedTime"]</th>
</tr>
</thead>
</abp-table>
</abp-card-body>
</abp-card>
</div>

3
modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/Index.cshtml.cs

@ -1,6 +1,9 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Volo.Docs.Documents;
namespace Volo.Docs.Admin.Pages.Docs.Admin.Documents namespace Volo.Docs.Admin.Pages.Docs.Admin.Documents
{ {

3
modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/index.css

@ -0,0 +1,3 @@
#DocumentsContainer .datepicker {
display: inline-block !important;
width: 7rem !important; }

71
modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/index.js

@ -1,8 +1,32 @@
$(function () { $(function () {
var l = abp.localization.getResource('Docs'); var l = abp.localization.getResource('Docs');
var service = window.volo.docs.admin.documentsAdmin;
var _dataTable = $('#DocumentsTable').DataTable(abp.libs.datatables.normalizeConfiguration({ var getFormattedDate = function ($datePicker) {
return $datePicker.data().datepicker.getFormattedDate("yyyy-mm-dd");
};
var getFilter = function () {
return {
projectId: $("#ProjectId").val(),
name: $("#Name").val(),
version: $("#Version").val(),
languageCode: $("#LanguageCode").val(),
fileName: $("#FileName").val(),
format: $("#Format").val(),
creationTimeMin: getFormattedDate($("#CreationTimeMin")),
creationTimeMax: getFormattedDate($("#CreationTimeMax")),
lastUpdatedTimeMin: getFormattedDate($("#LastUpdatedTimeMin")),
lastUpdatedTimeMax: getFormattedDate($("#LastUpdatedTimeMax")),
lastSignificantUpdateTimeMin: getFormattedDate($("#LastSignificantUpdateTimeMin")),
lastSignificantUpdateTimeMax: getFormattedDate($("#LastSignificantUpdateTimeMax")),
lastCachedTimeMin: getFormattedDate($("#LastCachedTimeMin")),
lastCachedTimeMax: getFormattedDate($("#LastCachedTimeMax"))
};
};
var dataTable = $('#DocumentsTable').DataTable(abp.libs.datatables.normalizeConfiguration({
processing: true, processing: true,
serverSide: true, serverSide: true,
scrollX: true, scrollX: true,
@ -10,7 +34,7 @@
searching: false, searching: false,
autoWidth: false, autoWidth: false,
scrollCollapse: true, scrollCollapse: true,
ajax: abp.libs.datatables.createAjax(volo.docs.admin.documentsAdmin.getAll), ajax: abp.libs.datatables.createAjax(service.getAll, getFilter),
columnDefs: [ columnDefs: [
{ {
rowAction: { rowAction: {
@ -21,11 +45,10 @@
visible: abp.auth.isGranted('Docs.Admin.Documents'), visible: abp.auth.isGranted('Docs.Admin.Documents'),
confirmMessage: function (data) { return l('RemoveFromCacheConfirmation'); }, confirmMessage: function (data) { return l('RemoveFromCacheConfirmation'); },
action: function (data) { action: function (data) {
volo.docs.admin.documentsAdmin service.removeFromCache(data.record.id)
.removeFromCache(data.record.id)
.then(function () { .then(function () {
abp.message.success(l('RemovedFromCache')); abp.message.success(l('RemovedFromCache'));
_dataTable.ajax.reload(); dataTable.ajax.reload();
}); });
} }
}, },
@ -34,11 +57,10 @@
visible: abp.auth.isGranted('Docs.Admin.Documents'), visible: abp.auth.isGranted('Docs.Admin.Documents'),
confirmMessage: function (data) { return l('ReIndexDocumentConfirmation'); }, confirmMessage: function (data) { return l('ReIndexDocumentConfirmation'); },
action: function (data) { action: function (data) {
volo.docs.admin.documentsAdmin service.reindex(data.record.id)
.reindex(data.record.id)
.then(function () { .then(function () {
abp.message.success(l('ReindexCompleted')); abp.message.success(l('ReindexCompleted'));
_dataTable.ajax.reload(); dataTable.ajax.reload();
}); });
} }
}, },
@ -47,11 +69,10 @@
visible: abp.auth.isGranted('Docs.Admin.Documents'), visible: abp.auth.isGranted('Docs.Admin.Documents'),
confirmMessage: function (data) { return l('DeleteDocumentFromDbConfirmation'); }, confirmMessage: function (data) { return l('DeleteDocumentFromDbConfirmation'); },
action: function (data) { action: function (data) {
volo.docs.admin.documentsAdmin service.deleteFromDatabase(data.record.id)
.deleteFromDatabase(data.record.id)
.then(function () { .then(function () {
abp.message.success(l('Deleted')); abp.message.success(l('Deleted'));
_dataTable.ajax.reload(); dataTable.ajax.reload();
}); });
} }
} }
@ -76,14 +97,7 @@
}, },
{ {
target: 5, target: 5,
data: "format", data: "format"
render: function (data) {
if (data === 'md') {
return 'markdown';
}
return data;
}
}, },
{ {
target: 6, target: 6,
@ -136,18 +150,15 @@
] ]
})); }));
$("#FilterForm input[type='text']").keypress(function (e) {
if (e.which === 13) {
dataTable.ajax.reload();
}
});
$("#ReIndexAllProjects").click(function (event) { $("#SearchButton").click(function (e) {
abp.message.confirm(l('ReIndexAllProjectConfirmationMessage')) e.preventDefault();
.done(function (accepted) { dataTable.ajax.reload();
if (accepted) {
volo.docs.admin.projectsAdmin
.reindexAll()
.then(function () {
abp.message.success(l('SuccessfullyReIndexAllProject'));
});
}
});
}); });
}); });

1
modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/index.min.css

@ -0,0 +1 @@
#DocumentsContainer .datepicker{display:inline-block !important;width:7rem !important;}

6
modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/index.scss

@ -0,0 +1,6 @@
#DocumentsContainer {
.datepicker {
display: inline-block !important;
width: 7rem !important;
}
}

8
modules/docs/src/Volo.Docs.Admin.Web/Volo.Docs.Admin.Web.csproj

@ -13,13 +13,16 @@
<TypeScriptToolsVersion>2.8</TypeScriptToolsVersion> <TypeScriptToolsVersion>2.8</TypeScriptToolsVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="CommonMark.NET" Version="0.15.1" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" /> <ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AutoMapper\Volo.Abp.AutoMapper.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Bundling\Volo.Abp.AspNetCore.Mvc.UI.Bundling.csproj" /> <ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Bundling\Volo.Abp.AspNetCore.Mvc.UI.Bundling.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.csproj" /> <ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Packages\Volo.Abp.AspNetCore.Mvc.UI.Packages.csproj" /> <ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Packages\Volo.Abp.AspNetCore.Mvc.UI.Packages.csproj" />
<ProjectReference Include="..\Volo.Docs.Admin.HttpApi\Volo.Docs.Admin.HttpApi.csproj" /> <ProjectReference Include="..\Volo.Docs.Admin.HttpApi\Volo.Docs.Admin.HttpApi.csproj" />
<PackageReference Include="CommonMark.NET" Version="0.15.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -29,8 +32,7 @@
<Content Remove="Pages\**\*.js" /> <Content Remove="Pages\**\*.js" />
<Content Remove="Properties\launchSettings.json" /> <Content Remove="Properties\launchSettings.json" />
<Content Remove="compilerconfig.json" /> <Content Remove="compilerconfig.json" />
<Content Remove="compilerconfig.json.defaults" /> <Content Remove="compilerconfig.json.defaults" />
<None Remove="Pages\Docs\Admin\Documents\index.js" />
<None Include="compilerconfig.json" /> <None Include="compilerconfig.json" />
<None Include="Properties\launchSettings.json" /> <None Include="Properties\launchSettings.json" />
</ItemGroup> </ItemGroup>

6
modules/docs/src/Volo.Docs.Admin.Web/compilerconfig.json

@ -0,0 +1,6 @@
[
{
"outputFile": "Pages/Docs/Admin/Documents/index.css",
"inputFile": "Pages/Docs/Admin/Documents/index.scss"
}
]

63
modules/docs/src/Volo.Docs.Admin.Web/compilerconfig.json.defaults

@ -0,0 +1,63 @@
{
"compilers": {
"less": {
"autoPrefix": "",
"cssComb": "none",
"ieCompat": true,
"strictMath": false,
"strictUnits": false,
"relativeUrls": true,
"rootPath": "",
"sourceMapRoot": "",
"sourceMapBasePath": "",
"sourceMap": false
},
"sass": {
"autoPrefix": "",
"includePath": "",
"indentType": "space",
"indentWidth": 2,
"outputStyle": "nested",
"Precision": 5,
"relativeUrls": true,
"sourceMapRoot": "",
"lineFeed": "",
"sourceMap": false
},
"stylus": {
"sourceMap": false
},
"babel": {
"sourceMap": false
},
"coffeescript": {
"bare": false,
"runtimeMode": "node",
"sourceMap": false
},
"handlebars": {
"root": "",
"noBOM": false,
"name": "",
"namespace": "",
"knownHelpersOnly": false,
"forcePartial": false,
"knownHelpers": [],
"commonjs": "",
"amd": false,
"sourceMap": false
}
},
"minifiers": {
"css": {
"enabled": true,
"termSemicolons": true,
"gzip": false
},
"javascript": {
"enabled": true,
"termSemicolons": true,
"gzip": false
}
}
}

4
modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainModule.cs

@ -4,7 +4,7 @@ using Microsoft.Extensions.Options;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.AutoMapper; using Volo.Abp.AutoMapper;
using Volo.Abp.Domain; using Volo.Abp.Domain;
using Volo.Abp.EventBus.Distributed; using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.Localization; using Volo.Abp.Localization;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.Threading; using Volo.Abp.Threading;
@ -34,7 +34,7 @@ namespace Volo.Docs
options.AddProfile<DocsDomainMappingProfile>(validate: true); options.AddProfile<DocsDomainMappingProfile>(validate: true);
}); });
Configure<AbpDistributedEventBusOptions>(options => Configure<AbpDistributedEntityEventOptions>(options =>
{ {
options.EtoMappings.Add<Document, DocumentEto>(typeof(DocsDomainModule)); options.EtoMappings.Add<Document, DocumentEto>(typeof(DocsDomainModule));
options.EtoMappings.Add<Project, ProjectEto>(typeof(DocsDomainModule)); options.EtoMappings.Add<Project, ProjectEto>(typeof(DocsDomainModule));

23
modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentRepository.cs

@ -23,10 +23,21 @@ namespace Volo.Docs.Documents
string version, string version,
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default);
Task<List<Document>> GetAllAsync(Guid? projectId, Task<List<Document>> GetAllAsync(
Guid? projectId,
string name, string name,
string version, string version,
string languageCode, string languageCode,
string fileName,
string format,
DateTime? creationTimeMin,
DateTime? creationTimeMax,
DateTime? lastUpdatedTimeMin,
DateTime? lastUpdatedTimeMax,
DateTime? lastSignificantUpdateTimeMin,
DateTime? lastSignificantUpdateTimeMax,
DateTime? lastCachedTimeMin,
DateTime? lastCachedTimeMax,
string sorting = null, string sorting = null,
int maxResultCount = int.MaxValue, int maxResultCount = int.MaxValue,
int skipCount = 0, int skipCount = 0,
@ -37,6 +48,16 @@ namespace Volo.Docs.Documents
string name, string name,
string version, string version,
string languageCode, string languageCode,
string fileName,
string format,
DateTime? creationTimeMin,
DateTime? creationTimeMax,
DateTime? lastUpdatedTimeMin,
DateTime? lastUpdatedTimeMax,
DateTime? lastSignificantUpdateTimeMin,
DateTime? lastSignificantUpdateTimeMax,
DateTime? lastCachedTimeMin,
DateTime? lastCachedTimeMax,
string sorting = null, string sorting = null,
int maxResultCount = int.MaxValue, int maxResultCount = int.MaxValue,
int skipCount = 0, int skipCount = 0,

103
modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Documents/EFCoreDocumentRepository.cs

@ -24,16 +24,44 @@ namespace Volo.Docs.Documents
return await DbSet.Where(d => d.ProjectId == projectId).ToListAsync(cancellationToken: cancellationToken); return await DbSet.Where(d => d.ProjectId == projectId).ToListAsync(cancellationToken: cancellationToken);
} }
public async Task<List<Document>> GetAllAsync(Guid? projectId, public async Task<List<Document>> GetAllAsync(
Guid? projectId,
string name, string name,
string version, string version,
string languageCode, string languageCode,
string fileName,
string format,
DateTime? creationTimeMin,
DateTime? creationTimeMax,
DateTime? lastUpdatedTimeMin,
DateTime? lastUpdatedTimeMax,
DateTime? lastSignificantUpdateTimeMin,
DateTime? lastSignificantUpdateTimeMax,
DateTime? lastCachedTimeMin,
DateTime? lastCachedTimeMax,
string sorting = null, string sorting = null,
int maxResultCount = int.MaxValue, int maxResultCount = int.MaxValue,
int skipCount = 0, int skipCount = 0,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
var query = ApplyFilterForGetAll(DbSet, projectId, name, version, languageCode); var query = ApplyFilterForGetAll(
DbSet,
projectId: projectId,
name: name,
version: version,
languageCode: languageCode,
format: format,
fileName: fileName,
creationTimeMin: creationTimeMin,
creationTimeMax: creationTimeMax,
lastUpdatedTimeMin: lastUpdatedTimeMin,
lastUpdatedTimeMax: lastUpdatedTimeMax,
lastSignificantUpdateTimeMin: lastSignificantUpdateTimeMin,
lastSignificantUpdateTimeMax: lastSignificantUpdateTimeMax,
lastCachedTimeMin: lastCachedTimeMin,
lastCachedTimeMax: lastCachedTimeMax
);
query = query.OrderBy(string.IsNullOrWhiteSpace(sorting) ? nameof(Document.Name) : sorting); query = query.OrderBy(string.IsNullOrWhiteSpace(sorting) ? nameof(Document.Name) : sorting);
return await query.PageBy(skipCount, maxResultCount).ToListAsync(cancellationToken); return await query.PageBy(skipCount, maxResultCount).ToListAsync(cancellationToken);
} }
@ -43,12 +71,39 @@ namespace Volo.Docs.Documents
string name, string name,
string version, string version,
string languageCode, string languageCode,
string fileName,
string format,
DateTime? creationTimeMin,
DateTime? creationTimeMax,
DateTime? lastUpdatedTimeMin,
DateTime? lastUpdatedTimeMax,
DateTime? lastSignificantUpdateTimeMin,
DateTime? lastSignificantUpdateTimeMax,
DateTime? lastCachedTimeMin,
DateTime? lastCachedTimeMax,
string sorting = null, string sorting = null,
int maxResultCount = int.MaxValue, int maxResultCount = int.MaxValue,
int skipCount = 0, int skipCount = 0,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
var query = ApplyFilterForGetAll(DbSet, projectId, name, version, languageCode); var query = ApplyFilterForGetAll(
DbSet,
projectId: projectId,
name: name,
version: version,
languageCode: languageCode,
format: format,
fileName: fileName,
creationTimeMin: creationTimeMin,
creationTimeMax: creationTimeMax,
lastUpdatedTimeMin: lastUpdatedTimeMin,
lastUpdatedTimeMax: lastUpdatedTimeMax,
lastSignificantUpdateTimeMin: lastSignificantUpdateTimeMin,
lastSignificantUpdateTimeMax: lastSignificantUpdateTimeMax,
lastCachedTimeMin: lastCachedTimeMin,
lastCachedTimeMax: lastCachedTimeMax
);
return await query.LongCountAsync(GetCancellationToken(cancellationToken)); return await query.LongCountAsync(GetCancellationToken(cancellationToken));
} }
@ -81,13 +136,47 @@ namespace Volo.Docs.Documents
string name, string name,
string version, string version,
string languageCode, string languageCode,
string fileName,
string format,
DateTime? creationTimeMin,
DateTime? creationTimeMax,
DateTime? lastUpdatedTimeMin,
DateTime? lastUpdatedTimeMax,
DateTime? lastSignificantUpdateTimeMin,
DateTime? lastSignificantUpdateTimeMax,
DateTime? lastCachedTimeMin,
DateTime? lastCachedTimeMax,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
return DbSet return DbSet
.WhereIf(projectId.HasValue, d => d.ProjectId == projectId.Value) .WhereIf(projectId.HasValue,
.WhereIf(name != null, d => d.Name != null && d.Name.Contains(name)) d => d.ProjectId == projectId.Value)
.WhereIf(version != null, d => d.Version != null && d.Version == version) .WhereIf(name != null,
.WhereIf(languageCode != null, d => d.LanguageCode != null && d.LanguageCode == languageCode); d => d.Name != null && d.Name.Contains(name))
.WhereIf(version != null,
d => d.Version != null && d.Version == version)
.WhereIf(languageCode != null,
d => d.LanguageCode != null && d.LanguageCode == languageCode)
.WhereIf(fileName != null,
d => d.FileName != null && d.FileName.Contains(fileName))
.WhereIf(format != null,
d => d.Format != null && d.Format == format)
.WhereIf(creationTimeMin.HasValue,
d => d.CreationTime.Date >= creationTimeMin.Value.Date)
.WhereIf(creationTimeMax.HasValue,
d => d.CreationTime.Date <= creationTimeMax.Value.Date)
.WhereIf(lastUpdatedTimeMin.HasValue,
d => d.LastUpdatedTime.Date >= lastUpdatedTimeMin.Value.Date)
.WhereIf(lastUpdatedTimeMax.HasValue,
d => d.LastUpdatedTime.Date <= lastUpdatedTimeMax.Value.Date)
.WhereIf(lastSignificantUpdateTimeMin.HasValue,
d => d.LastSignificantUpdateTime != null && d.LastSignificantUpdateTime.Value.Date >= lastSignificantUpdateTimeMin.Value.Date)
.WhereIf(lastSignificantUpdateTimeMax.HasValue,
d => d.LastSignificantUpdateTime != null && d.LastSignificantUpdateTime.Value.Date <= lastSignificantUpdateTimeMax.Value.Date)
.WhereIf(lastCachedTimeMin.HasValue,
d => d.LastCachedTime.Date >= lastCachedTimeMin.Value.Date)
.WhereIf(lastCachedTimeMax.HasValue,
d => d.LastCachedTime.Date <= lastCachedTimeMax.Value.Date);
} }
} }
} }

124
modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs

@ -43,33 +43,88 @@ namespace Volo.Docs.Documents
x.Version == version, cancellationToken: cancellationToken); x.Version == version, cancellationToken: cancellationToken);
} }
public async Task<List<Document>> GetAllAsync(Guid? projectId, public async Task<List<Document>> GetAllAsync(
Guid? projectId,
string name, string name,
string version, string version,
string languageCode, string languageCode,
string fileName,
string format,
DateTime? creationTimeMin,
DateTime? creationTimeMax,
DateTime? lastUpdatedTimeMin,
DateTime? lastUpdatedTimeMax,
DateTime? lastSignificantUpdateTimeMin,
DateTime? lastSignificantUpdateTimeMax,
DateTime? lastCachedTimeMin,
DateTime? lastCachedTimeMax,
string sorting = null, string sorting = null,
int maxResultCount = int.MaxValue, int maxResultCount = int.MaxValue,
int skipCount = 0, int skipCount = 0,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
return await return await
ApplyFilterForGetAll(GetMongoQueryable(), projectId, name, version, languageCode) ApplyFilterForGetAll(
.OrderBy(string.IsNullOrWhiteSpace(sorting) ? "name asc" : sorting).As<IMongoQueryable<Document>>() GetMongoQueryable(),
.PageBy<Document, IMongoQueryable<Document>>(skipCount, maxResultCount) projectId: projectId,
.ToListAsync(GetCancellationToken(cancellationToken)); name: name,
version: version,
languageCode: languageCode,
format: format,
fileName: fileName,
creationTimeMin: creationTimeMin,
creationTimeMax: creationTimeMax,
lastUpdatedTimeMin: lastUpdatedTimeMin,
lastUpdatedTimeMax: lastUpdatedTimeMax,
lastSignificantUpdateTimeMin: lastSignificantUpdateTimeMin,
lastSignificantUpdateTimeMax: lastSignificantUpdateTimeMax,
lastCachedTimeMin: lastCachedTimeMin,
lastCachedTimeMax: lastCachedTimeMax)
.OrderBy(string.IsNullOrWhiteSpace(sorting) ? "name asc" : sorting).As<IMongoQueryable<Document>>()
.PageBy<Document, IMongoQueryable<Document>>(skipCount, maxResultCount)
.ToListAsync(GetCancellationToken(cancellationToken));
} }
public async Task<long> GetAllCountAsync(Guid? projectId, public async Task<long> GetAllCountAsync(
Guid? projectId,
string name, string name,
string version, string version,
string languageCode, string languageCode,
string fileName,
string format,
DateTime? creationTimeMin,
DateTime? creationTimeMax,
DateTime? lastUpdatedTimeMin,
DateTime? lastUpdatedTimeMax,
DateTime? lastSignificantUpdateTimeMin,
DateTime? lastSignificantUpdateTimeMax,
DateTime? lastCachedTimeMin,
DateTime? lastCachedTimeMax,
string sorting = null, string sorting = null,
int maxResultCount = int.MaxValue, int maxResultCount = int.MaxValue,
int skipCount = 0, int skipCount = 0,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
return await return await
ApplyFilterForGetAll(GetMongoQueryable(), projectId, name, version, languageCode) ApplyFilterForGetAll(
GetMongoQueryable(),
projectId: projectId,
name: name,
version: version,
languageCode: languageCode,
format: format,
fileName: fileName,
creationTimeMin: creationTimeMin,
creationTimeMax: creationTimeMax,
lastUpdatedTimeMin: lastUpdatedTimeMin,
lastUpdatedTimeMax: lastUpdatedTimeMax,
lastSignificantUpdateTimeMin: lastSignificantUpdateTimeMin,
lastSignificantUpdateTimeMax: lastSignificantUpdateTimeMax,
lastCachedTimeMin: lastCachedTimeMin,
lastCachedTimeMax: lastCachedTimeMax)
.OrderBy(string.IsNullOrWhiteSpace(sorting) ? "name asc" : sorting).As<IMongoQueryable<Document>>() .OrderBy(string.IsNullOrWhiteSpace(sorting) ? "name asc" : sorting).As<IMongoQueryable<Document>>()
.PageBy<Document, IMongoQueryable<Document>>(skipCount, maxResultCount) .PageBy<Document, IMongoQueryable<Document>>(skipCount, maxResultCount)
.LongCountAsync(GetCancellationToken(cancellationToken)); .LongCountAsync(GetCancellationToken(cancellationToken));
@ -86,6 +141,16 @@ namespace Volo.Docs.Documents
string name, string name,
string version, string version,
string languageCode, string languageCode,
string fileName,
string format,
DateTime? creationTimeMin,
DateTime? creationTimeMax,
DateTime? lastUpdatedTimeMin,
DateTime? lastUpdatedTimeMax,
DateTime? lastSignificantUpdateTimeMin,
DateTime? lastSignificantUpdateTimeMax,
DateTime? lastCachedTimeMin,
DateTime? lastCachedTimeMax,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
if (projectId.HasValue) if (projectId.HasValue)
@ -108,6 +173,51 @@ namespace Volo.Docs.Documents
query = query.Where(d => d.LanguageCode != null && d.LanguageCode == languageCode); query = query.Where(d => d.LanguageCode != null && d.LanguageCode == languageCode);
} }
if (fileName != null)
{
query = query.Where(d => d.FileName != null && d.FileName.Contains(fileName));
}
if (creationTimeMin.HasValue)
{
query = query.Where(d => d.CreationTime.Date >= creationTimeMin.Value.Date);
}
if (creationTimeMax.HasValue)
{
query = query.Where(d => d.CreationTime.Date <= creationTimeMax.Value.Date);
}
if (lastUpdatedTimeMin.HasValue)
{
query = query.Where(d => d.LastUpdatedTime.Date >= lastUpdatedTimeMin.Value.Date);
}
if (lastUpdatedTimeMax.HasValue)
{
query = query.Where(d => d.LastUpdatedTime.Date <= lastUpdatedTimeMax.Value.Date);
}
if (lastSignificantUpdateTimeMin.HasValue)
{
query = query.Where(d => d.LastSignificantUpdateTime != null && d.LastSignificantUpdateTime.Value.Date >= lastSignificantUpdateTimeMin.Value.Date);
}
if (lastSignificantUpdateTimeMax.HasValue)
{
query = query.Where(d => d.LastSignificantUpdateTime != null && d.LastSignificantUpdateTime.Value.Date <= lastSignificantUpdateTimeMax.Value.Date);
}
if (lastCachedTimeMin.HasValue)
{
query = query.Where(d => d.LastCachedTime.Date >= lastCachedTimeMin.Value.Date);
}
if (lastCachedTimeMax.HasValue)
{
query = query.Where(d => d.LastCachedTime.Date <= lastCachedTimeMax.Value.Date);
}
return query; return query;
} }
} }

4
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/AbpIdentityDomainModule.cs

@ -4,7 +4,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Volo.Abp.AutoMapper; using Volo.Abp.AutoMapper;
using Volo.Abp.Domain; using Volo.Abp.Domain;
using Volo.Abp.EventBus.Distributed; using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.ObjectExtending; using Volo.Abp.ObjectExtending;
using Volo.Abp.ObjectExtending.Modularity; using Volo.Abp.ObjectExtending.Modularity;
@ -29,7 +29,7 @@ namespace Volo.Abp.Identity
options.AddProfile<IdentityDomainMappingProfile>(validate: true); options.AddProfile<IdentityDomainMappingProfile>(validate: true);
}); });
Configure<AbpDistributedEventBusOptions>(options => Configure<AbpDistributedEntityEventOptions>(options =>
{ {
options.EtoMappings.Add<IdentityUser, UserEto>(typeof(AbpIdentityDomainModule)); options.EtoMappings.Add<IdentityUser, UserEto>(typeof(AbpIdentityDomainModule));
options.EtoMappings.Add<IdentityClaimType, IdentityClaimTypeEto>(typeof(AbpIdentityDomainModule)); options.EtoMappings.Add<IdentityClaimType, IdentityClaimTypeEto>(typeof(AbpIdentityDomainModule));

9
modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/AbpIdentityDomainTestModule.cs

@ -1,5 +1,6 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Authorization.Permissions; using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.Identity.EntityFrameworkCore; using Volo.Abp.Identity.EntityFrameworkCore;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.PermissionManagement.Identity; using Volo.Abp.PermissionManagement.Identity;
@ -14,6 +15,14 @@ namespace Volo.Abp.Identity
)] )]
public class AbpIdentityDomainTestModule : AbpModule public class AbpIdentityDomainTestModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpDistributedEntityEventOptions>(options =>
{
options.AutoEventSelectors.Add<IdentityUser>();
});
}
public override void OnApplicationInitialization(ApplicationInitializationContext context) public override void OnApplicationInitialization(ApplicationInitializationContext context)
{ {
SeedTestData(context); SeedTestData(context);

15
modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/Distributed_User_Change_Event_Tests.cs

@ -2,6 +2,7 @@
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Shouldly; using Shouldly;
using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.EventBus.Distributed; using Volo.Abp.EventBus.Distributed;
using Volo.Abp.Testing.Utils; using Volo.Abp.Testing.Utils;
using Volo.Abp.Uow; using Volo.Abp.Uow;
@ -28,11 +29,17 @@ namespace Volo.Abp.Identity
} }
[Fact] [Fact]
public async Task Should_Register_Handler() public void Should_Register_Handler()
{ {
var options = GetRequiredService<IOptions<AbpDistributedEventBusOptions>>().Value; GetRequiredService<IOptions<AbpDistributedEntityEventOptions>>()
options.EtoMappings.ShouldContain(m => m.Key == typeof(IdentityUser) && m.Value.EtoType == typeof(UserEto)); .Value
options.Handlers.ShouldContain(h => h == typeof(DistributedUserUpdateHandler)); .EtoMappings
.ShouldContain(m => m.Key == typeof(IdentityUser) && m.Value.EtoType == typeof(UserEto));
GetRequiredService<IOptions<AbpDistributedEventBusOptions>>()
.Value
.Handlers
.ShouldContain(h => h == typeof(DistributedUserUpdateHandler));
} }
[Fact] [Fact]

4
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs

@ -6,7 +6,7 @@ using Microsoft.Extensions.Options;
using Volo.Abp.AutoMapper; using Volo.Abp.AutoMapper;
using Volo.Abp.BackgroundWorkers; using Volo.Abp.BackgroundWorkers;
using Volo.Abp.Caching; using Volo.Abp.Caching;
using Volo.Abp.EventBus.Distributed; using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.Identity; using Volo.Abp.Identity;
using Volo.Abp.IdentityServer.ApiResources; using Volo.Abp.IdentityServer.ApiResources;
using Volo.Abp.IdentityServer.Clients; using Volo.Abp.IdentityServer.Clients;
@ -41,7 +41,7 @@ namespace Volo.Abp.IdentityServer
options.AddProfile<IdentityServerAutoMapperProfile>(validate: true); options.AddProfile<IdentityServerAutoMapperProfile>(validate: true);
}); });
Configure<AbpDistributedEventBusOptions>(options => Configure<AbpDistributedEntityEventOptions>(options =>
{ {
options.EtoMappings.Add<ApiResource, ApiResourceEto>(typeof(AbpIdentityServerDomainModule)); options.EtoMappings.Add<ApiResource, ApiResourceEto>(typeof(AbpIdentityServerDomainModule));
options.EtoMappings.Add<Client, ClientEto>(typeof(AbpIdentityServerDomainModule)); options.EtoMappings.Add<Client, ClientEto>(typeof(AbpIdentityServerDomainModule));

4
modules/tenant-management/src/Volo.Abp.TenantManagement.Domain/Volo/Abp/TenantManagement/AbpTenantManagementDomainModule.cs

@ -2,7 +2,7 @@
using Volo.Abp.AutoMapper; using Volo.Abp.AutoMapper;
using Volo.Abp.Data; using Volo.Abp.Data;
using Volo.Abp.Domain; using Volo.Abp.Domain;
using Volo.Abp.EventBus.Distributed; using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.UI; using Volo.Abp.UI;
@ -26,7 +26,7 @@ namespace Volo.Abp.TenantManagement
options.AddProfile<AbpTenantManagementDomainMappingProfile>(validate: true); options.AddProfile<AbpTenantManagementDomainMappingProfile>(validate: true);
}); });
Configure<AbpDistributedEventBusOptions>(options => Configure<AbpDistributedEntityEventOptions>(options =>
{ {
options.EtoMappings.Add<Tenant, TenantEto>(); options.EtoMappings.Add<Tenant, TenantEto>();
}); });

7
npm/ng-packs/packages/core/src/lib/services/list.service.ts

@ -1,6 +1,6 @@
import { Inject, Injectable, OnDestroy, Optional } from '@angular/core'; import { Inject, Injectable, OnDestroy, Optional } from '@angular/core';
import { BehaviorSubject, Observable, ReplaySubject } from 'rxjs'; import { BehaviorSubject, Observable, of, ReplaySubject } from 'rxjs';
import { debounceTime, shareReplay, switchMap, tap } from 'rxjs/operators'; import { catchError, debounceTime, filter, shareReplay, switchMap, tap } from 'rxjs/operators';
import { ABP } from '../models/common'; import { ABP } from '../models/common';
import { PagedResultDto } from '../models/dtos'; import { PagedResultDto } from '../models/dtos';
import { LIST_QUERY_DEBOUNCE_TIME } from '../tokens/list.token'; import { LIST_QUERY_DEBOUNCE_TIME } from '../tokens/list.token';
@ -88,7 +88,8 @@ export class ListService<QueryParamsType = ABP.PageQueryParams> implements OnDes
this._isLoading$.next(true); this._isLoading$.next(true);
return this.query$.pipe( return this.query$.pipe(
switchMap(streamCreatorCallback), switchMap(query => streamCreatorCallback(query).pipe(catchError(() => of(null)))),
filter(Boolean),
tap(() => this._isLoading$.next(false)), tap(() => this._isLoading$.next(false)),
shareReplay({ bufferSize: 1, refCount: true }), shareReplay({ bufferSize: 1, refCount: true }),
takeUntilDestroy(this), takeUntilDestroy(this),

13
npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts

@ -36,8 +36,15 @@ export class NgxDatatableListDirective implements OnChanges, OnDestroy, OnInit {
private subscribeToSort() { private subscribeToSort() {
const sub = this.table.sort.subscribe(({ sorts: [{ prop, dir }] }) => { const sub = this.table.sort.subscribe(({ sorts: [{ prop, dir }] }) => {
this.list.sortKey = prop; if (prop === this.list.sortKey && this.list.sortOrder === 'desc') {
this.list.sortOrder = dir; this.list.sortKey = '';
this.list.sortOrder = '';
this.table.sorts = [];
this.cdRef.detectChanges();
} else {
this.list.sortKey = prop;
this.list.sortOrder = dir;
}
}); });
this.subscription.add(sub); this.subscription.add(sub);
} }
@ -45,7 +52,7 @@ export class NgxDatatableListDirective implements OnChanges, OnDestroy, OnInit {
private subscribeToIsLoading() { private subscribeToIsLoading() {
const sub = this.list.isLoading$.subscribe(loading => { const sub = this.list.isLoading$.subscribe(loading => {
this.table.loadingIndicator = loading; this.table.loadingIndicator = loading;
this.cdRef.markForCheck(); this.cdRef.detectChanges();
}); });
this.subscription.add(sub); this.subscription.add(sub);
} }

1
samples/MicroserviceDemo/applications/BackendAdminApp.Host/BackendAdminAppHostModule.cs

@ -8,7 +8,6 @@ using ProductManagement;
using StackExchange.Redis; using StackExchange.Redis;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
using MsDemo.Shared; using MsDemo.Shared;
using Swashbuckle.AspNetCore.Swagger;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.AspNetCore.Authentication.OAuth; using Volo.Abp.AspNetCore.Authentication.OAuth;
using Volo.Abp.AspNetCore.Mvc.Client; using Volo.Abp.AspNetCore.Mvc.Client;

6
samples/MicroserviceDemo/microservices/IdentityService.Host/IdentityServiceHostModule.cs

@ -13,6 +13,7 @@ using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
using Volo.Abp.AuditLogging.EntityFrameworkCore; using Volo.Abp.AuditLogging.EntityFrameworkCore;
using Volo.Abp.Autofac; using Volo.Abp.Autofac;
using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.SqlServer; using Volo.Abp.EntityFrameworkCore.SqlServer;
using Volo.Abp.EventBus.RabbitMq; using Volo.Abp.EventBus.RabbitMq;
@ -77,6 +78,11 @@ namespace IdentityService.Host
{ {
options.UseSqlServer(); options.UseSqlServer();
}); });
Configure<AbpDistributedEntityEventOptions>(options =>
{
options.AutoEventSelectors.Add<IdentityUser>();
});
context.Services.AddStackExchangeRedisCache(options => context.Services.AddStackExchangeRedisCache(options =>
{ {

Loading…
Cancel
Save