Browse Source

Merge branch 'dev' into akin/added-metaDescription-field-in-blog

pull/3432/head
Alper Ebicoglu 7 years ago
parent
commit
e73f9e10df
  1. 4
      docs/en/API/Dynamic-CSharp-API-Clients.md
  2. 4
      docs/en/Authorization.md
  3. 4
      docs/en/Best-Practices/Entity-Framework-Core-Integration.md
  4. 4
      docs/en/Best-Practices/MongoDB-Integration.md
  5. 1
      docs/en/CLI.md
  6. 2
      docs/en/Modules/Docs.md
  7. 4
      docs/en/UI/Angular/Track-By-Service.md
  8. 4
      docs/en/UI/AspNetCore/Bundling-Minification.md
  9. 62
      docs/en/UI/Common/Utils/Linked-List.md
  10. 9
      docs/en/docs-nav.json
  11. 4
      docs/zh-Hans/API/Dynamic-CSharp-API-Clients.md
  12. 4
      docs/zh-Hans/Authorization.md
  13. 4
      docs/zh-Hans/Best-Practices/Entity-Framework-Core-Integration.md
  14. 6
      docs/zh-Hans/Best-Practices/MongoDB-Integration.md
  15. 12
      docs/zh-Hans/UI/AspNetCore/Bundling-Minification.md
  16. 2
      framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperExtensibleDtoExtensions.cs
  17. 1
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs
  18. 10
      framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs
  19. 135
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions.cs
  20. 14
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs
  21. 1
      framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/AbpObjectExtendingTestModule.cs
  22. 4
      framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions_Tests.cs
  23. 17
      modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Files/RawFileDto.cs
  24. 18
      modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Files/FileAppService.cs
  25. 1
      npm/ng-packs/package.json
  26. 33
      npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts
  27. 16
      npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts
  28. 15
      npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.html
  29. 27
      npm/ng-packs/packages/theme-shared/src/lib/animations/collapse.animations.ts
  30. 12
      npm/ng-packs/yarn.lock
  31. 2
      npm/packs/utils/abp.resourcemapping.js
  32. 2
      npm/packs/utils/package.json
  33. 3
      npm/packs/utils/projects/utils/ng-package.json

4
docs/en/API/Dynamic-CSharp-API-Clients.md

@ -69,7 +69,7 @@ public class MyClientAppModule : AbpModule
} }
```` ````
See the "RemoteServiceOptions" section below for more detailed configuration. See the "AbpRemoteServiceOptions" section below for more detailed configuration.
## Usage ## Usage
@ -104,7 +104,7 @@ While you can inject `IBookAppService` like above to use the client proxy, you c
## Configuration ## Configuration
### RemoteServiceOptions ### AbpRemoteServiceOptions
`AbpRemoteServiceOptions` is automatically set from the `appsettings.json` by default. Alternatively, you can use `Configure` method to set or override it. Example: `AbpRemoteServiceOptions` is automatically set from the `appsettings.json` by default. Alternatively, you can use `Configure` method to set or override it. Example:

4
docs/en/Authorization.md

@ -339,10 +339,10 @@ A permission value provider should return one of the following values from the `
- `PermissionGrantResult.Prohibited` is returned to prohibit the user for the permission. If any of the providers return `Prohibited`, the result will always be `Prohibited`. Doesn't matter what other providers return. - `PermissionGrantResult.Prohibited` is returned to prohibit the user for the permission. If any of the providers return `Prohibited`, the result will always be `Prohibited`. Doesn't matter what other providers return.
- `PermissionGrantResult.Undefined` is returned if this value provider could not decide about the permission value. Return this to let other providers check the permission. - `PermissionGrantResult.Undefined` is returned if this value provider could not decide about the permission value. Return this to let other providers check the permission.
Once a provider is defined, it should be added to the `PermissionOptions` as shown below: Once a provider is defined, it should be added to the `AbpPermissionOptions` as shown below:
```csharp ```csharp
Configure<PermissionOptions>(options => Configure<AbpPermissionOptions>(options =>
{ {
options.ValueProviders.Add<SystemAdminPermissionValueProvider>(); options.ValueProviders.Add<SystemAdminPermissionValueProvider>();
}); });

4
docs/en/Best-Practices/Entity-Framework-Core-Integration.md

@ -107,10 +107,10 @@ public static class IdentityDbContextModelBuilderExtensions
```` ````
* **Do** call `b.ConfigureByConvention();` for each entity mapping (as shown above). * **Do** call `b.ConfigureByConvention();` for each entity mapping (as shown above).
* **Do** create a **configuration options** class by inheriting from the `ModelBuilderConfigurationOptions`. Example: * **Do** create a **configuration options** class by inheriting from the `AbpModelBuilderConfigurationOptions`. Example:
````C# ````C#
public class IdentityModelBuilderConfigurationOptions : ModelBuilderConfigurationOptions public class IdentityModelBuilderConfigurationOptions : AbpModelBuilderConfigurationOptions
{ {
public IdentityModelBuilderConfigurationOptions() public IdentityModelBuilderConfigurationOptions()
: base(AbpIdentityConsts.DefaultDbTablePrefix, AbpIdentityConsts.DefaultDbSchema) : base(AbpIdentityConsts.DefaultDbTablePrefix, AbpIdentityConsts.DefaultDbSchema)

4
docs/en/Best-Practices/MongoDB-Integration.md

@ -90,11 +90,11 @@ public static class AbpIdentityMongoDbContextExtensions
} }
``` ```
- **Do** create a **configuration options** class by inheriting from the `MongoModelBuilderConfigurationOptions`. Example: - **Do** create a **configuration options** class by inheriting from the `AbpMongoModelBuilderConfigurationOptions`. Example:
```c# ```c#
public class IdentityMongoModelBuilderConfigurationOptions public class IdentityMongoModelBuilderConfigurationOptions
: MongoModelBuilderConfigurationOptions : AbpMongoModelBuilderConfigurationOptions
{ {
public IdentityMongoModelBuilderConfigurationOptions() public IdentityMongoModelBuilderConfigurationOptions()
: base(AbpIdentityConsts.DefaultDbTablePrefix) : base(AbpIdentityConsts.DefaultDbTablePrefix)

1
docs/en/CLI.md

@ -60,6 +60,7 @@ abp new Acme.BookStore
* `--version` or `-v`: Specifies the ABP & template version. It can be a [release tag](https://github.com/abpframework/abp/releases) or a [branch name](https://github.com/abpframework/abp/branches). Uses the latest release if not specified. Most of the times, you will want to use the latest version. * `--version` or `-v`: Specifies the ABP & template version. It can be a [release tag](https://github.com/abpframework/abp/releases) or a [branch name](https://github.com/abpframework/abp/branches). Uses the latest release if not specified. Most of the times, you will want to use the latest version.
* `--template-source` or `-ts`: Specifies a custom template source to use to build the project. Local and network sources can be used(Like `D\localTemplate` or `https://<your url>.zip`). * `--template-source` or `-ts`: Specifies a custom template source to use to build the project. Local and network sources can be used(Like `D\localTemplate` or `https://<your url>.zip`).
* `--create-solution-folder` or `-csf`: Specifies if the project will be in a new folder in the output folder or directly the output folder. * `--create-solution-folder` or `-csf`: Specifies if the project will be in a new folder in the output folder or directly the output folder.
* `--connection-string` or `-cs`: Overwrites the default connection strings in all `appsettings.json` files. The default connection string is `Server=localhost;Database=MyProjectName;Trusted_Connection=True;MultipleActiveResultSets=true`. You can set your own connection string if you don't want to use the default. Be aware that the default database provider is `SQL Server`, therefore you can only enter connection string for SQL Server!
### add-package ### add-package

2
docs/en/Modules/Docs.md

@ -134,7 +134,7 @@ An ABP module must declare `[DependsOn]` attribute if it has a dependency upon a
{ {
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
Configure<PermissionOptions>(options => Configure<AbpPermissionOptions>(options =>
{ {
options.DefinitionProviders.Add<MyProjectPermissionDefinitionProvider>(); options.DefinitionProviders.Add<MyProjectPermissionDefinitionProvider>();
}); });

4
docs/en/UI/Angular/Track-By-Service.md

@ -111,7 +111,3 @@ class DemoComponent {
trackByTenantAccountId = trackByDeep<Item>('tenant', 'account', 'id'); trackByTenantAccountId = trackByDeep<Item>('tenant', 'account', 'id');
} }
``` ```
## What's Next?
* [Linked List (Doubly)](./Linked-List.md)

4
docs/en/UI/AspNetCore/Bundling-Minification.md

@ -246,10 +246,10 @@ public class MyPrismjsStyleExtension : BundleContributor
} }
```` ````
Then you can configure `BundleContributorOptions` to extend existing `PrismjsStyleBundleContributor`. Then you can configure `AbpBundleContributorOptions` to extend existing `PrismjsStyleBundleContributor`.
````csharp ````csharp
Configure<BundleContributorOptions>(options => Configure<AbpBundleContributorOptions>(options =>
{ {
options options
.Extensions<PrismjsStyleBundleContributor>() .Extensions<PrismjsStyleBundleContributor>()

62
docs/en/UI/Angular/Linked-List.md → docs/en/UI/Common/Utils/Linked-List.md

@ -130,7 +130,11 @@ list.addTail({ x: 3 });
// {"x":1} <-> {"x":2} <-> {"x":3} // {"x":1} <-> {"x":2} <-> {"x":3}
list.addAfter({ x: 0 }, { x: 2 }, (v1, v2) => v1.x === v2.x); list.addAfter(
{ x: 0 },
2,
(value, searchedValue) => value.x === searchedValue
);
// {"x":1} <-> {"x":2} <-> {"x":0} <-> {"x":3} // {"x":1} <-> {"x":2} <-> {"x":0} <-> {"x":3}
``` ```
@ -164,7 +168,11 @@ list.addManyTail([{ x: 1 },{ x: 2 },{ x: 3 }]);
// {"x":1} <-> {"x":2} <-> {"x":3} // {"x":1} <-> {"x":2} <-> {"x":3}
list.addManyAfter([{ x: 4 }, { x: 5 }], { x: 2 }, (v1, v2) => v1.x === v2.x); list.addManyAfter(
[{ x: 4 }, { x: 5 }],
2,
(value, searchedValue) => value.x === searchedValue
);
// {"x":1} <-> {"x":2} <-> {"x":4} <-> {"x":5} <-> {"x":3} // {"x":1} <-> {"x":2} <-> {"x":4} <-> {"x":5} <-> {"x":3}
``` ```
@ -203,7 +211,11 @@ list.addTail({ x: 3 });
// {"x":1} <-> {"x":2} <-> {"x":3} // {"x":1} <-> {"x":2} <-> {"x":3}
list.addBefore({ x: 0 }, { x: 2 }, (v1, v2) => v1.x === v2.x); list.addBefore(
{ x: 0 },
2,
(value, searchedValue) => value.x === searchedValue
);
// {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":3} // {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":3}
``` ```
@ -237,7 +249,11 @@ list.addManyTail([{ x: 1 },{ x: 2 },{ x: 3 }]);
// {"x":1} <-> {"x":2} <-> {"x":3} // {"x":1} <-> {"x":2} <-> {"x":3}
list.addManyBefore([{ x: 4 }, { x: 5 }], { x: 2 }, (v1, v2) => v1.x === v2.x); list.addManyBefore(
[{ x: 4 }, { x: 5 }],
2,
(value, searchedValue) => value.x === searchedValue
);
// {"x":1} <-> {"x":4} <-> {"x":5} <-> {"x":2} <-> {"x":3} // {"x":1} <-> {"x":4} <-> {"x":5} <-> {"x":2} <-> {"x":3}
``` ```
@ -388,7 +404,9 @@ list.add({ x: 3 }).tail();
// {"x":1} <-> {"x":2} <-> {"x":3} // {"x":1} <-> {"x":2} <-> {"x":3}
list.add({ x: 0 }).after({ x: 2 }, (v1, v2) => v1.x === v2.x); list
.add({ x: 0 })
.after(2, (value, searchedValue) => value.x === searchedValue);
// {"x":1} <-> {"x":2} <-> {"x":0} <-> {"x":3} // {"x":1} <-> {"x":2} <-> {"x":0} <-> {"x":3}
``` ```
@ -429,7 +447,9 @@ list.add({ x: 3 }).tail();
// {"x":1} <-> {"x":2} <-> {"x":3} // {"x":1} <-> {"x":2} <-> {"x":3}
list.add({ x: 0 }).before({ x: 2 }, (v1, v2) => v1.x === v2.x); list
.add({ x: 0 })
.before(2, (value, searchedValue) => value.x === searchedValue);
// {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":3} // {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":3}
``` ```
@ -543,7 +563,9 @@ list.addMany([{ x: 1 }, { x: 2 }, { x: 3 }]).tail();
// {"x":1} <-> {"x":2} <-> {"x":3} // {"x":1} <-> {"x":2} <-> {"x":3}
list.addMany([{ x: 4 }, { x: 5 }]).after({ x: 2 }, (v1, v2) => v1.x === v2.x); list
.addMany([{ x: 4 }, { x: 5 }])
.after(2, (value, searchedValue) => value.x === searchedValue);
// {"x":1} <-> {"x":2} <-> {"x":4} <-> {"x":5} <-> {"x":3} // {"x":1} <-> {"x":2} <-> {"x":4} <-> {"x":5} <-> {"x":3}
``` ```
@ -579,7 +601,9 @@ list.addMany([{ x: 1 }, { x: 2 }, { x: 3 }]).tail();
// {"x":1} <-> {"x":2} <-> {"x":3} // {"x":1} <-> {"x":2} <-> {"x":3}
list.addMany([{ x: 4 }, { x: 5 }]).before({ x: 2 }, (v1, v2) => v1.x === v2.x); list
.addMany([{ x: 4 }, { x: 5 }])
.before(2, (value, searchedValue) => value.x === searchedValue);
// {"x":1} <-> {"x":4} <-> {"x":5} <-> {"x":2} <-> {"x":3} // {"x":1} <-> {"x":4} <-> {"x":5} <-> {"x":2} <-> {"x":3}
``` ```
@ -779,7 +803,7 @@ list.addMany([{ x: 1 }, { x: 0 }, { x: 2 }, { x: 0 }, { x: 3 }]).tail();
// {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3} // {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3}
list.dropByValue({ x: 0 }, (v1, v2) => v1.x === v2.x); list.dropByValue(0, (value, searchedValue) => value.x === searchedValue);
// {"x":1} <-> {"x":2} <-> {"x":0} <-> {"x":3} // {"x":1} <-> {"x":2} <-> {"x":0} <-> {"x":3}
``` ```
@ -813,7 +837,7 @@ list.addMany([{ x: 1 }, { x: 0 }, { x: 2 }, { x: 0 }, { x: 3 }]).tail();
// {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3} // {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3}
list.dropByValue({ x: 0 }, (v1, v2) => v1.x === v2.x); list.dropByValue(0, (value, searchedValue) => value.x === searchedValue);
// {"x":1} <-> {"x":2} <-> {"x":3} // {"x":1} <-> {"x":2} <-> {"x":3}
``` ```
@ -921,7 +945,9 @@ list.addMany([{ x: 1 }, { x: 0 }, { x: 2 }, { x: 0 }, { x: 3 }]).tail();
// {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3} // {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3}
list.drop().byValue({ x: 0 }, (v1, v2) => v1.x === v2.x); list
.drop()
.byValue(0, (value, searchedValue) => value.x === searchedValue);
// {"x":1} <-> {"x":2} <-> {"x":0} <-> {"x":3} // {"x":1} <-> {"x":2} <-> {"x":0} <-> {"x":3}
``` ```
@ -957,7 +983,9 @@ list.addMany([{ x: 1 }, { x: 0 }, { x: 2 }, { x: 0 }, { x: 3 }]).tail();
// {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3} // {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3}
list.drop().byValueAll({ x: 0 }, (v1, v2) => v1.x === v2.x); list
.drop()
.byValueAll(0, (value, searchedValue) => value.x === searchedValue);
// {"x":1} <-> {"x":2} <-> {"x":3} // {"x":1} <-> {"x":2} <-> {"x":3}
``` ```
@ -1145,11 +1173,11 @@ list.addTailMany([{ x: 1 }, { x: 0 }, { x: 2 }, { x: 0 }, { x: 3 }]);
// {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3} // {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3}
const i0 = indexOf({ x: 1 }, (v1, v2) => v1.x === v2.x); const i0 = indexOf(1, (value, searchedValue) => value.x === searchedValue);
const i1 = indexOf({ x: 2 }, (v1, v2) => v1.x === v2.x); const i1 = indexOf(2, (value, searchedValue) => value.x === searchedValue);
const i2 = indexOf({ x: 3 }, (v1, v2) => v1.x === v2.x); const i2 = indexOf(3, (value, searchedValue) => value.x === searchedValue);
const i3 = indexOf({ x: 0 }, (v1, v2) => v1.x === v2.x); const i3 = indexOf(0, (value, searchedValue) => value.x === searchedValue);
const i4 = indexOf({ x: 4 }, (v1, v2) => v1.x === v2.x); const i4 = indexOf(4, (value, searchedValue) => value.x === searchedValue);
/* /*
i0 === 0 i0 === 0

9
docs/en/docs-nav.json

@ -344,10 +344,15 @@
{ {
"text": "TrackByService", "text": "TrackByService",
"path": "UI/Angular/Track-By-Service.md" "path": "UI/Angular/Track-By-Service.md"
}, }
]
},
{
"text": "Common",
"items": [
{ {
"text": "Linked List (Doubly)", "text": "Linked List (Doubly)",
"path": "UI/Angular/Linked-List.md" "path": "UI/Common/Utils/Linked-List.md"
} }
] ]
} }

4
docs/zh-Hans/API/Dynamic-CSharp-API-Clients.md

@ -69,7 +69,7 @@ public class MyClientAppModule : AbpModule
} }
```` ````
查看下面的"RemoteServiceOptions"章节获取更多详细配置. 查看下面的"AbpRemoteServiceOptions"章节获取更多详细配置.
## 使用 ## 使用
@ -104,7 +104,7 @@ public class MyService : ITransientDependency
## 配置 ## 配置
### RemoteServiceOptions ### AbpRemoteServiceOptions
默认情况下`AbpRemoteServiceOptions`从`appsettings.json`获取.或者,你可以使用`Configure`方法来设置或重写它.如: 默认情况下`AbpRemoteServiceOptions`从`appsettings.json`获取.或者,你可以使用`Configure`方法来设置或重写它.如:

4
docs/zh-Hans/Authorization.md

@ -340,10 +340,10 @@ public class SystemAdminPermissionValueProvider : PermissionValueProvider
* `PermissionGrantResult.Prohibited` 禁止授权用户,任何一个授权值提供程序返回了 `Prohibited`, 那么其他的提供程序返回的值都不再重要. * `PermissionGrantResult.Prohibited` 禁止授权用户,任何一个授权值提供程序返回了 `Prohibited`, 那么其他的提供程序返回的值都不再重要.
* `PermissionGrantResult.Undefined` 代表当前无法确定是否授予或禁止权限, 返回`UnDefined`由其他权限值提供程序检查权限. * `PermissionGrantResult.Undefined` 代表当前无法确定是否授予或禁止权限, 返回`UnDefined`由其他权限值提供程序检查权限.
定义`Provider`后将其添加到 `PermissionOptions`,如下所示: 定义`Provider`后将其添加到 `AbpPermissionOptions`,如下所示:
````csharp ````csharp
Configure<PermissionOptions>(options => Configure<AbpPermissionOptions>(options =>
{ {
options.ValueProviders.Add<SystemAdminPermissionValueProvider>(); options.ValueProviders.Add<SystemAdminPermissionValueProvider>();
}); });

4
docs/zh-Hans/Best-Practices/Entity-Framework-Core-Integration.md

@ -106,10 +106,10 @@ public static class IdentityDbContextModelBuilderExtensions
```` ````
* **推荐** 为每个Enttiy映射调用 `b.ConfigureByConvention();`(如上所示). * **推荐** 为每个Enttiy映射调用 `b.ConfigureByConvention();`(如上所示).
* **推荐** 通过继承 `ModelBuilderConfigurationOptions` 来创建 **configuration Options** 类. 例如: * **推荐** 通过继承 `AbpModelBuilderConfigurationOptions` 来创建 **configuration Options** 类. 例如:
````C# ````C#
public class IdentityModelBuilderConfigurationOptions : ModelBuilderConfigurationOptions public class IdentityModelBuilderConfigurationOptions : AbpModelBuilderConfigurationOptions
{ {
public IdentityModelBuilderConfigurationOptions() public IdentityModelBuilderConfigurationOptions()
: base(AbpIdentityConsts.DefaultDbTablePrefix, AbpIdentityConsts.DefaultDbSchema) : base(AbpIdentityConsts.DefaultDbTablePrefix, AbpIdentityConsts.DefaultDbSchema)

6
docs/zh-Hans/Best-Practices/MongoDB-Integration.md

@ -1,4 +1,4 @@
## MongoDB 集成 ## MongoDB 集成
* **推荐** 为每个模块定义一个独立的 `MongoDbContext` 接口与实现类. * **推荐** 为每个模块定义一个独立的 `MongoDbContext` 接口与实现类.
@ -90,11 +90,11 @@ public static class AbpIdentityMongoDbContextExtensions
} }
``` ```
- **推荐** 通过继承 `MongoModelBuilderConfigurationOptions` 来创建 **configuration Options** 类. 示例: - **推荐** 通过继承 `AbpMongoModelBuilderConfigurationOptions` 来创建 **configuration Options** 类. 示例:
```c# ```c#
public class IdentityMongoModelBuilderConfigurationOptions public class IdentityMongoModelBuilderConfigurationOptions
: MongoModelBuilderConfigurationOptions : AbpMongoModelBuilderConfigurationOptions
{ {
public IdentityMongoModelBuilderConfigurationOptions() public IdentityMongoModelBuilderConfigurationOptions()
: base(AbpIdentityConsts.DefaultDbTablePrefix) : base(AbpIdentityConsts.DefaultDbTablePrefix)

12
docs/zh-Hans/UI/AspNetCore/Bundling-Minification.md

@ -115,7 +115,7 @@ public class MyWebModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
Configure<BundlingOptions>(options => Configure<AbpBundlingOptions>(options =>
{ {
options options
.ScriptBundles .ScriptBundles
@ -153,7 +153,7 @@ public class MyWebExtensionModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
Configure<BundlingOptions>(options => Configure<AbpBundlingOptions>(options =>
{ {
options options
.ScriptBundles .ScriptBundles
@ -191,7 +191,7 @@ public class MyExtensionGlobalStyleContributor : BundleContributor
然后你可以按照下面的代码使用这个贡献者: 然后你可以按照下面的代码使用这个贡献者:
````C# ````C#
services.Configure<BundlingOptions>(options => services.Configure<AbpBundlingOptions>(options =>
{ {
options options
.ScriptBundles .ScriptBundles
@ -248,10 +248,10 @@ public class MyPrismjsStyleExtension : BundleContributor
} }
```` ````
然后你可以配置 `BundleContributorOptions` 去扩展已存在的 `PrismjsStyleBundleContributor`. 然后你可以配置 `AbpBundleContributorOptions` 去扩展已存在的 `PrismjsStyleBundleContributor`.
````csharp ````csharp
Configure<BundleContributorOptions>(options => Configure<AbpBundleContributorOptions>(options =>
{ {
options options
.Extensions<PrismjsStyleBundleContributor>() .Extensions<PrismjsStyleBundleContributor>()
@ -319,7 +319,7 @@ namespace MyCompany.MyProject
例如: 例如:
````c# ````c#
services.Configure<BundlingOptions>(options => services.Configure<AbpBundlingOptions>(options =>
{ {
options options
.StyleBundles .StyleBundles

2
framework/src/Volo.Abp.AutoMapper/AutoMapper/AbpAutoMapperExtensibleDtoExtensions.cs

@ -8,7 +8,7 @@ namespace AutoMapper
{ {
public static IMappingExpression<TSource, TDestination> MapExtraProperties<TSource, TDestination>( public static IMappingExpression<TSource, TDestination> MapExtraProperties<TSource, TDestination>(
this IMappingExpression<TSource, TDestination> mappingExpression, this IMappingExpression<TSource, TDestination> mappingExpression,
MappingPropertyDefinitionChecks definitionChecks = MappingPropertyDefinitionChecks.Both) MappingPropertyDefinitionChecks? definitionChecks = null)
where TDestination : IHasExtraProperties where TDestination : IHasExtraProperties
where TSource : IHasExtraProperties where TSource : IHasExtraProperties
{ {

1
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs

@ -218,6 +218,7 @@ namespace Volo.Abp.Cli.Commands
sb.AppendLine(" abp new Acme.BookStore -t module --no-ui"); sb.AppendLine(" abp new Acme.BookStore -t module --no-ui");
sb.AppendLine(" abp new Acme.BookStore -ts \"D:\\localTemplate\\abp\""); sb.AppendLine(" abp new Acme.BookStore -ts \"D:\\localTemplate\\abp\"");
sb.AppendLine(" abp new Acme.BookStore --local-framework-ref --abp-path \"D:\\github\\abp\""); sb.AppendLine(" abp new Acme.BookStore --local-framework-ref --abp-path \"D:\\github\\abp\"");
sb.AppendLine(" abp new Acme.BookStore --connection-string \"Server=myServerName\\myInstanceName;Database=myDatabase;User Id=myUsername;Password=myPassword\"");
sb.AppendLine(""); sb.AppendLine("");
sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI"); sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI");

10
framework/src/Volo.Abp.IdentityModel/Volo/Abp/IdentityModel/IdentityModelAuthenticationService.cs

@ -70,9 +70,17 @@ namespace Volo.Abp.IdentityModel
} }
var tokenResponse = await GetTokenResponse(discoveryResponse, configuration); var tokenResponse = await GetTokenResponse(discoveryResponse, configuration);
if (tokenResponse.IsError) if (tokenResponse.IsError)
{ {
throw new AbpException($"Could not get token from the OpenId Connect server! ErrorType: {tokenResponse.ErrorType}. Error: {tokenResponse.Error}. ErrorDescription: {tokenResponse.ErrorDescription}. HttpStatusCode: {tokenResponse.HttpStatusCode}"); if (tokenResponse.ErrorDescription != null)
{
throw new AbpException($"Could not get token from the OpenId Connect server! ErrorType: {tokenResponse.ErrorType}. Error: {tokenResponse.Error}. ErrorDescription: {tokenResponse.ErrorDescription}. HttpStatusCode: {tokenResponse.HttpStatusCode}");
}
var rawError = tokenResponse.Raw;
var withoutInnerException = rawError.Split(new string[] { "<eof/>" }, StringSplitOptions.RemoveEmptyEntries);
throw new AbpException(withoutInnerException[0]);
} }
return tokenResponse.AccessToken; return tokenResponse.AccessToken;

135
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions.cs

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using JetBrains.Annotations; using JetBrains.Annotations;
using Volo.Abp.Data; using Volo.Abp.Data;
@ -25,7 +24,7 @@ namespace Volo.Abp.ObjectExtending
public static void MapExtraPropertiesTo<TSource, TDestination>( public static void MapExtraPropertiesTo<TSource, TDestination>(
[NotNull] this TSource source, [NotNull] this TSource source,
[NotNull] TDestination destination, [NotNull] TDestination destination,
MappingPropertyDefinitionChecks definitionChecks = MappingPropertyDefinitionChecks.Both) MappingPropertyDefinitionChecks? definitionChecks = null)
where TSource : IHasExtraProperties where TSource : IHasExtraProperties
where TDestination : IHasExtraProperties where TDestination : IHasExtraProperties
{ {
@ -58,7 +57,7 @@ namespace Volo.Abp.ObjectExtending
public static void MapExtraPropertiesTo<TSource, TDestination>( public static void MapExtraPropertiesTo<TSource, TDestination>(
[NotNull] Dictionary<string, object> sourceDictionary, [NotNull] Dictionary<string, object> sourceDictionary,
[NotNull] Dictionary<string, object> destinationDictionary, [NotNull] Dictionary<string, object> destinationDictionary,
MappingPropertyDefinitionChecks definitionChecks = MappingPropertyDefinitionChecks.Both) MappingPropertyDefinitionChecks? definitionChecks = null)
where TSource : IHasExtraProperties where TSource : IHasExtraProperties
where TDestination : IHasExtraProperties where TDestination : IHasExtraProperties
{ {
@ -90,7 +89,7 @@ namespace Volo.Abp.ObjectExtending
[NotNull] Type destinationType, [NotNull] Type destinationType,
[NotNull] Dictionary<string, object> sourceDictionary, [NotNull] Dictionary<string, object> sourceDictionary,
[NotNull] Dictionary<string, object> destinationDictionary, [NotNull] Dictionary<string, object> destinationDictionary,
MappingPropertyDefinitionChecks definitionChecks = MappingPropertyDefinitionChecks.Both) MappingPropertyDefinitionChecks? definitionChecks = null)
{ {
Check.AssignableTo<IHasExtraProperties>(sourceType, nameof(sourceType)); Check.AssignableTo<IHasExtraProperties>(sourceType, nameof(sourceType));
Check.AssignableTo<IHasExtraProperties>(destinationType, nameof(destinationType)); Check.AssignableTo<IHasExtraProperties>(destinationType, nameof(destinationType));
@ -98,78 +97,120 @@ namespace Volo.Abp.ObjectExtending
Check.NotNull(destinationDictionary, nameof(destinationDictionary)); Check.NotNull(destinationDictionary, nameof(destinationDictionary));
var sourceObjectExtension = ObjectExtensionManager.Instance.GetOrNull(sourceType); var sourceObjectExtension = ObjectExtensionManager.Instance.GetOrNull(sourceType);
if (definitionChecks.HasFlag(MappingPropertyDefinitionChecks.Source) &&
sourceObjectExtension == null)
{
return;
}
var destinationObjectExtension = ObjectExtensionManager.Instance.GetOrNull(destinationType); var destinationObjectExtension = ObjectExtensionManager.Instance.GetOrNull(destinationType);
if (definitionChecks.HasFlag(MappingPropertyDefinitionChecks.Destination) &&
destinationObjectExtension == null)
{
return;
}
if (definitionChecks == MappingPropertyDefinitionChecks.None) foreach (var keyValue in sourceDictionary)
{ {
foreach (var keyValue in sourceDictionary) if (CanMapProperty(
keyValue.Key,
sourceObjectExtension,
destinationObjectExtension,
definitionChecks))
{ {
destinationDictionary[keyValue.Key] = keyValue.Value; destinationDictionary[keyValue.Key] = keyValue.Value;
} }
} }
else if (definitionChecks == MappingPropertyDefinitionChecks.Source) }
{
Debug.Assert(sourceObjectExtension != null, nameof(sourceObjectExtension) + " != null"); //TODO: Move these methods to a class like ObjectExtensionHelper
public static bool CanMapProperty<TSource, TDestination>(
[NotNull] string propertyName,
MappingPropertyDefinitionChecks? definitionChecks = null)
{
return CanMapProperty(
typeof(TSource),
typeof(TDestination),
propertyName,
definitionChecks
);
}
public static bool CanMapProperty(
[NotNull] Type sourceType,
[NotNull] Type destinationType,
[NotNull] string propertyName,
MappingPropertyDefinitionChecks? definitionChecks = null)
{
Check.AssignableTo<IHasExtraProperties>(sourceType, nameof(sourceType));
Check.AssignableTo<IHasExtraProperties>(destinationType, nameof(destinationType));
Check.NotNull(propertyName, nameof(propertyName));
var sourceObjectExtension = ObjectExtensionManager.Instance.GetOrNull(sourceType);
var destinationObjectExtension = ObjectExtensionManager.Instance.GetOrNull(destinationType);
return CanMapProperty(
propertyName,
sourceObjectExtension,
destinationObjectExtension,
definitionChecks);
}
foreach (var property in sourceObjectExtension.GetProperties()) private static bool CanMapProperty(
[NotNull] string propertyName,
[CanBeNull] ObjectExtensionInfo sourceObjectExtension,
[CanBeNull] ObjectExtensionInfo destinationObjectExtension,
MappingPropertyDefinitionChecks? definitionChecks = null)
{
Check.NotNull(propertyName, nameof(propertyName));
if (definitionChecks != null)
{
if (definitionChecks.Value.HasFlag(MappingPropertyDefinitionChecks.Source))
{ {
if (!sourceDictionary.ContainsKey(property.Name)) if (sourceObjectExtension == null)
{ {
continue; return false;
} }
destinationDictionary[property.Name] = sourceDictionary[property.Name]; if (!sourceObjectExtension.HasProperty(propertyName))
{
return false;
}
} }
}
else if (definitionChecks == MappingPropertyDefinitionChecks.Destination)
{
Debug.Assert(destinationObjectExtension != null, nameof(destinationObjectExtension) + " != null");
foreach (var keyValue in sourceDictionary) if (definitionChecks.Value.HasFlag(MappingPropertyDefinitionChecks.Destination))
{ {
if (!destinationObjectExtension.HasProperty(keyValue.Key)) if (destinationObjectExtension == null)
{ {
continue; return false;
} }
destinationDictionary[keyValue.Key] = keyValue.Value; if (!destinationObjectExtension.HasProperty(propertyName))
{
return false;
}
} }
return true;
} }
else if (definitionChecks == MappingPropertyDefinitionChecks.Both) else
{ {
Debug.Assert(sourceObjectExtension != null, nameof(sourceObjectExtension) + " != null"); var sourcePropertyDefinition = sourceObjectExtension?.GetPropertyOrNull(propertyName);
Debug.Assert(destinationObjectExtension != null, nameof(destinationObjectExtension) + " != null"); var destinationPropertyDefinition = destinationObjectExtension?.GetPropertyOrNull(propertyName);
foreach (var property in sourceObjectExtension.GetProperties()) if (sourcePropertyDefinition != null)
{ {
if (!sourceDictionary.ContainsKey(property.Name)) if (destinationPropertyDefinition != null)
{ {
continue; return true;
} }
if (!destinationObjectExtension.HasProperty(property.Name)) if (sourcePropertyDefinition.CheckPairDefinitionOnMapping == false)
{ {
continue; return true;
} }
destinationDictionary[property.Name] = sourceDictionary[property.Name];
} }
} else if (destinationPropertyDefinition != null)
else {
{ if (destinationPropertyDefinition.CheckPairDefinitionOnMapping == false)
throw new NotImplementedException(definitionChecks + " was not implemented!"); {
return true;
}
}
return false;
} }
} }
} }
} }

14
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs

@ -15,6 +15,20 @@ namespace Volo.Abp.ObjectExtending
[NotNull] [NotNull]
public Type Type { get; } public Type Type { get; }
/// <summary>
/// Indicates whether to check the other side of the object mapping
/// if it explicitly defines the property. This property is used in;
///
/// * .MapExtraPropertiesTo() extension method.
/// * .MapExtraProperties() configuration for the AutoMapper.
///
/// It this is true, these methods check if the mapping object
/// has defined the property using the <see cref="ObjectExtensionManager"/>.
///
/// Default: null (unspecified, uses the default logic).
/// </summary>
public bool? CheckPairDefinitionOnMapping { get; set; }
[NotNull] [NotNull]
public Dictionary<object, object> Configuration { get; } public Dictionary<object, object> Configuration { get; }

1
framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/AbpObjectExtendingTestModule.cs

@ -19,6 +19,7 @@ namespace Volo.Abp.ObjectExtending
ObjectExtensionManager.Instance ObjectExtensionManager.Instance
.AddOrUpdateProperty<ExtensibleTestPerson, string>("Name") .AddOrUpdateProperty<ExtensibleTestPerson, string>("Name")
.AddOrUpdateProperty<ExtensibleTestPerson, int>("Age") .AddOrUpdateProperty<ExtensibleTestPerson, int>("Age")
.AddOrUpdateProperty<ExtensibleTestPerson, string>("NoPairCheck", options => options.CheckPairDefinitionOnMapping = false)
.AddOrUpdateProperty<ExtensibleTestPersonDto, string>("Name") .AddOrUpdateProperty<ExtensibleTestPersonDto, string>("Name")
.AddOrUpdateProperty<ExtensibleTestPersonDto, int>("ChildCount"); .AddOrUpdateProperty<ExtensibleTestPersonDto, int>("ChildCount");
}); });

4
framework/test/Volo.Abp.ObjectExtending.Tests/Volo/Abp/ObjectExtending/HasExtraPropertiesObjectExtendingExtensions_Tests.cs

@ -16,7 +16,8 @@ namespace Volo.Abp.ObjectExtending
.SetProperty("Name", "John") .SetProperty("Name", "John")
.SetProperty("Age", 42) .SetProperty("Age", 42)
.SetProperty("ChildCount", 2) .SetProperty("ChildCount", 2)
.SetProperty("Sex", "male"); .SetProperty("Sex", "male")
.SetProperty("NoPairCheck", "test-value");
_personDto = new ExtensibleTestPersonDto() _personDto = new ExtensibleTestPersonDto()
.SetProperty("ExistingDtoProperty", "existing-value"); .SetProperty("ExistingDtoProperty", "existing-value");
@ -31,6 +32,7 @@ namespace Volo.Abp.ObjectExtending
_personDto.HasProperty("Age").ShouldBeFalse(); //Not defined on the destination _personDto.HasProperty("Age").ShouldBeFalse(); //Not defined on the destination
_personDto.HasProperty("ChildCount").ShouldBeFalse(); //Not defined in the source _personDto.HasProperty("ChildCount").ShouldBeFalse(); //Not defined in the source
_personDto.HasProperty("Sex").ShouldBeFalse(); //Not defined in both classes _personDto.HasProperty("Sex").ShouldBeFalse(); //Not defined in both classes
_personDto.GetProperty<string>("NoPairCheck").ShouldBe("test-value"); //CheckPairDefinitionOnMapping = false
_personDto.GetProperty<string>("ExistingDtoProperty").ShouldBe("existing-value"); //Should not clear existing values _personDto.GetProperty<string>("ExistingDtoProperty").ShouldBe("existing-value"); //Should not clear existing values
} }

17
modules/blogging/src/Volo.Blogging.Application.Contracts/Volo/Blogging/Files/RawFileDto.cs

@ -1,7 +1,22 @@
namespace Volo.Blogging.Files using System.Security.Cryptography;
using Volo.Abp.Threading;
namespace Volo.Blogging.Files
{ {
public class RawFileDto public class RawFileDto
{ {
public byte[] Bytes { get; set; } public byte[] Bytes { get; set; }
public bool IsFileEmpty => Bytes == null || Bytes.Length == 0;
public RawFileDto()
{
}
public static RawFileDto EmptyResult()
{
return new RawFileDto() {Bytes = new byte[0]};
}
} }
} }

18
modules/blogging/src/Volo.Blogging.Application/Volo/Blogging/Files/FileAppService.cs

@ -2,6 +2,7 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.Validation; using Volo.Abp.Validation;
@ -12,9 +13,11 @@ namespace Volo.Blogging.Files
public class FileAppService : BloggingAppServiceBase, IFileAppService public class FileAppService : BloggingAppServiceBase, IFileAppService
{ {
public BlogFileOptions Options { get; } public BlogFileOptions Options { get; }
private readonly ILogger<FileAppService> _logger;
public FileAppService(IOptions<BlogFileOptions> options) public FileAppService(IOptions<BlogFileOptions> options, ILogger<FileAppService> logger)
{ {
_logger = logger;
Options = options.Value; Options = options.Value;
} }
@ -35,12 +38,13 @@ namespace Volo.Blogging.Files
var filePath = Path.Combine(Options.FileUploadLocalFolder, name); var filePath = Path.Combine(Options.FileUploadLocalFolder, name);
return Task.FromResult( if (File.Exists(filePath))
new RawFileDto {
{ return Task.FromResult(new RawFileDto {Bytes = File.ReadAllBytes(filePath)});
Bytes = File.ReadAllBytes(filePath) }
}
); _logger.LogError($"Cannot find the file {filePath}");
return Task.FromResult(RawFileDto.EmptyResult());
} }
public virtual Task<FileUploadOutputDto> CreateAsync(FileUploadInputDto input) public virtual Task<FileUploadOutputDto> CreateAsync(FileUploadInputDto input)

1
npm/ng-packs/package.json

@ -34,6 +34,7 @@
"@abp/ng.tenant-management.config": "~2.3.0", "@abp/ng.tenant-management.config": "~2.3.0",
"@abp/ng.theme.basic": "~2.3.0", "@abp/ng.theme.basic": "~2.3.0",
"@abp/ng.theme.shared": "^2.3.0", "@abp/ng.theme.shared": "^2.3.0",
"@abp/utils": "~2.3.0",
"@angular-builders/jest": "^8.2.0", "@angular-builders/jest": "^8.2.0",
"@angular-devkit/build-angular": "~0.803.21", "@angular-devkit/build-angular": "~0.803.21",
"@angular-devkit/build-ng-packagr": "~0.803.21", "@angular-devkit/build-ng-packagr": "~0.803.21",

33
npm/ng-packs/packages/core/src/lib/tests/initial-utils.spec.ts

@ -1,10 +1,10 @@
import { getInitialData, localeInitializer } from '../utils'; import { Component, Injector } from '@angular/core';
import { Injector } from '@angular/core'; import { createComponentFactory, Spectator } from '@ngneat/spectator/jest';
import { Spectator, createComponentFactory } from '@ngneat/spectator/jest';
import { Component } from '@angular/core';
import { Store } from '@ngxs/store'; import { Store } from '@ngxs/store';
import { OAuthService } from 'angular-oauth2-oidc';
import { of } from 'rxjs'; import { of } from 'rxjs';
import { GetAppConfiguration } from '../actions'; import { GetAppConfiguration } from '../actions';
import { getInitialData, localeInitializer } from '../utils';
@Component({ @Component({
selector: 'abp-dummy', selector: 'abp-dummy',
@ -14,7 +14,10 @@ export class DummyComponent {}
describe('InitialUtils', () => { describe('InitialUtils', () => {
let spectator: Spectator<DummyComponent>; let spectator: Spectator<DummyComponent>;
const createComponent = createComponentFactory({ component: DummyComponent, mocks: [Store] }); const createComponent = createComponentFactory({
component: DummyComponent,
mocks: [Store],
});
beforeEach(() => (spectator = createComponent())); beforeEach(() => (spectator = createComponent()));
@ -25,7 +28,8 @@ describe('InitialUtils', () => {
const store = spectator.get(Store); const store = spectator.get(Store);
const dispatchSpy = jest.spyOn(store, 'dispatch'); const dispatchSpy = jest.spyOn(store, 'dispatch');
injectorSpy.mockReturnValue(store); injectorSpy.mockReturnValueOnce(store);
injectorSpy.mockReturnValueOnce({ hasValidAccessToken: () => false });
dispatchSpy.mockReturnValue(of('test')); dispatchSpy.mockReturnValue(of('test'));
expect(typeof getInitialData(injector)).toBe('function'); expect(typeof getInitialData(injector)).toBe('function');
@ -34,6 +38,23 @@ describe('InitialUtils', () => {
}); });
}); });
describe('#checkAccessToken', () => {
test('should call logOut fn of OAuthService when token is valid and current user not found', async () => {
const injector = spectator.get(Injector);
const injectorSpy = jest.spyOn(injector, 'get');
const store = spectator.get(Store);
const dispatchSpy = jest.spyOn(store, 'dispatch');
const logOutFn = jest.fn();
injectorSpy.mockReturnValueOnce(store);
injectorSpy.mockReturnValueOnce({ hasValidAccessToken: () => true, logOut: logOutFn });
dispatchSpy.mockReturnValue(of({ currentUser: { id: null } }));
getInitialData(injector)();
expect(logOutFn).toHaveBeenCalled();
});
});
describe('#localeInitializer', () => { describe('#localeInitializer', () => {
test('should resolve registerLocale', async () => { test('should resolve registerLocale', async () => {
const injector = spectator.get(Injector); const injector = spectator.get(Injector);

16
npm/ng-packs/packages/core/src/lib/utils/initial-utils.ts

@ -3,17 +3,31 @@ import { Injector } from '@angular/core';
import { Store } from '@ngxs/store'; import { Store } from '@ngxs/store';
import { GetAppConfiguration } from '../actions/config.actions'; import { GetAppConfiguration } from '../actions/config.actions';
import differentLocales from '../constants/different-locales'; import differentLocales from '../constants/different-locales';
import { ApplicationConfiguration } from '../models/application-configuration';
import { tap } from 'rxjs/operators';
import { ConfigState } from '../states/config.state';
import { OAuthService } from 'angular-oauth2-oidc';
export function getInitialData(injector: Injector) { export function getInitialData(injector: Injector) {
const fn = () => { const fn = () => {
const store: Store = injector.get(Store); const store: Store = injector.get(Store);
return store.dispatch(new GetAppConfiguration()).toPromise(); return store
.dispatch(new GetAppConfiguration())
.pipe(tap(res => checkAccessToken(store, injector)))
.toPromise();
}; };
return fn; return fn;
} }
function checkAccessToken(store: Store, injector: Injector) {
const oAuth = injector.get(OAuthService);
if (oAuth.hasValidAccessToken() && !store.selectSnapshot(ConfigState.getDeep('currentUser.id'))) {
oAuth.logOut();
}
}
export function localeInitializer(injector: Injector) { export function localeInitializer(injector: Injector) {
const fn = () => { const fn = () => {
const store: Store = injector.get(Store); const store: Store = injector.get(Store);

15
npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.html

@ -195,8 +195,19 @@
</ng-template> </ng-template>
<ng-template #currentUser> <ng-template #currentUser>
<li *ngIf="(currentUser$ | async)?.isAuthenticated" class="nav-item"> <li class="nav-item">
<div ngbDropdown class="dropdown" #currentUserDropdown="ngbDropdown" display="static"> <ng-template #loginBtn>
<a role="button" class="nav-link" routerLink="/account/login">{{
'AbpAccount::Login' | abpLocalization
}}</a>
</ng-template>
<div
*ngIf="(currentUser$ | async)?.isAuthenticated; else loginBtn"
ngbDropdown
class="dropdown"
#currentUserDropdown="ngbDropdown"
display="static"
>
<a <a
ngbDropdownToggle ngbDropdownToggle
class="nav-link" class="nav-link"

27
npm/ng-packs/packages/theme-shared/src/lib/animations/collapse.animations.ts

@ -1,4 +1,12 @@
import { animate, animation, trigger, state, style, transition, useAnimation } from '@angular/animations'; import {
animate,
animation,
trigger,
state,
style,
transition,
useAnimation,
} from '@angular/animations';
export const collapseY = animation( export const collapseY = animation(
[ [
@ -9,7 +17,10 @@ export const collapseY = animation(
); );
export const collapseYWithMargin = animation( export const collapseYWithMargin = animation(
[style({ 'margin-top': '0' }), animate('{{ time }} {{ easing }}', style({ 'margin-top': '-100%' }))], [
style({ 'margin-top': '0' }),
animate('{{ time }} {{ easing }}', style({ 'margin-left': '-100%' })),
],
{ {
params: { time: '500ms', easing: 'ease' }, params: { time: '500ms', easing: 'ease' },
}, },
@ -32,7 +43,10 @@ export const expandY = animation(
); );
export const expandYWithMargin = animation( export const expandYWithMargin = animation(
[style({ 'margin-top': '-100%' }), animate('{{ time }} {{ easing }}', style({ 'margin-top': '0' }))], [
style({ 'margin-top': '-100%' }),
animate('{{ time }} {{ easing }}', style({ 'margin-top': '0' })),
],
{ {
params: { time: '500ms', easing: 'ease' }, params: { time: '500ms', easing: 'ease' },
}, },
@ -63,11 +77,14 @@ export const collapseWithMargin = trigger('collapseWithMargin', [
]); ]);
export const collapseLinearWithMargin = trigger('collapseLinearWithMargin', [ export const collapseLinearWithMargin = trigger('collapseLinearWithMargin', [
state('collapsed', style({ 'margin-top': '-100%' })), state('collapsed', style({ 'margin-top': '-100vh' })),
state('expanded', style({ 'margin-top': '0' })), state('expanded', style({ 'margin-top': '0' })),
transition( transition(
'expanded => collapsed', 'expanded => collapsed',
useAnimation(collapseYWithMargin, { params: { time: '200ms', easing: 'linear' } }), useAnimation(collapseYWithMargin, { params: { time: '200ms', easing: 'linear' } }),
), ),
transition('collapsed => expanded', useAnimation(expandYWithMargin, { params: { time: '250ms', easing: 'linear' } })), transition(
'collapsed => expanded',
useAnimation(expandYWithMargin, { params: { time: '250ms', easing: 'linear' } }),
),
]); ]);

12
npm/ng-packs/yarn.lock

@ -120,6 +120,13 @@
chart.js "^2.9.3" chart.js "^2.9.3"
tslib "^1.9.0" tslib "^1.9.0"
"@abp/utils@~2.3.0":
version "2.3.1"
resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-2.3.1.tgz#728b978d598a98b643562250be54c92988b986e5"
integrity sha512-sZ1nrl8pV1Zx3WAqHRUQ2V3aJlsjaq1ggg2VIPYY4FjCYHFZ3L+Fkq5cPPZb/MczG1YZpAQiMtCJ/+8slvPHHQ==
dependencies:
just-compare "^1.3.0"
"@angular-builders/jest@^8.2.0": "@angular-builders/jest@^8.2.0":
version "8.3.2" version "8.3.2"
resolved "https://registry.yarnpkg.com/@angular-builders/jest/-/jest-8.3.2.tgz#669c350c9df2e3afc9ae048c5067759c36113728" resolved "https://registry.yarnpkg.com/@angular-builders/jest/-/jest-8.3.2.tgz#669c350c9df2e3afc9ae048c5067759c36113728"
@ -9578,11 +9585,6 @@ pretty-format@^24.0.0, pretty-format@^24.3.0, pretty-format@^24.8.0, pretty-form
ansi-styles "^3.2.0" ansi-styles "^3.2.0"
react-is "^16.8.4" react-is "^16.8.4"
primeicons@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/primeicons/-/primeicons-2.0.0.tgz#ec3e5a8d4d04a09309225a5a57deb911e08dc0d3"
integrity sha512-GJTCeMSQU8UU1GqbsaDrg/IH+b/vSinJQl52NVpdJ7sShYLZA8Eq6jLF48Ye3N/dQloGrE07i7XsZvxQ9pNbqg==
private@^0.1.6: private@^0.1.6:
version "0.1.8" version "0.1.8"
resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"

2
npm/packs/utils/abp.resourcemapping.js

@ -1,5 +1,5 @@
module.exports = { module.exports = {
mappings: { mappings: {
'@node_modules/@abp/utils/bundles/*': '@libs/abp/utils/', '@node_modules/@abp/utils/dist/bundles/*.*': '@libs/abp/utils/',
}, },
}; };

2
npm/packs/utils/package.json

@ -1,6 +1,6 @@
{ {
"name": "@abp/utils", "name": "@abp/utils",
"version": "2.3.1", "version": "2.3.2",
"scripts": { "scripts": {
"prepublish": "yarn install --ignore-scripts && node prepublish.js", "prepublish": "yarn install --ignore-scripts && node prepublish.js",
"ng": "ng", "ng": "ng",

3
npm/packs/utils/projects/utils/ng-package.json

@ -3,7 +3,8 @@
"dest": "../../dist", "dest": "../../dist",
"deleteDestPath": true, "deleteDestPath": true,
"lib": { "lib": {
"entryFile": "src/public-api.ts" "entryFile": "src/public-api.ts",
"umdId": "abp.utils.common"
}, },
"whitelistedNonPeerDependencies": ["just-compare"] "whitelistedNonPeerDependencies": ["just-compare"]
} }

Loading…
Cancel
Save