From df28a8e73b59e85d85d7a42a071707e5302e2bc7 Mon Sep 17 00:00:00 2001 From: bnymncoskuner Date: Thu, 1 Apr 2021 10:29:16 +0300 Subject: [PATCH 01/14] docs: add docs for page component --- docs/en/UI/Angular/Page-Component.md | 211 +++++++++++++++++++++++++++ docs/en/docs-nav.json | 9 ++ 2 files changed, 220 insertions(+) create mode 100644 docs/en/UI/Angular/Page-Component.md diff --git a/docs/en/UI/Angular/Page-Component.md b/docs/en/UI/Angular/Page-Component.md new file mode 100644 index 0000000000..a019990be1 --- /dev/null +++ b/docs/en/UI/Angular/Page-Component.md @@ -0,0 +1,211 @@ +# Page Component + +ABP provides a component that wraps your content with some built-in components to recude the amount of code you need to write. + +If the template of a component looks like as follows, you can utilize the `abp-page` components. + +E.g. + +`app.component.ts` + +```html +
+
+

{{ '::AppTitle' | abpLocalization }}

+
+ +
+ +
+
+ +
+ +
+``` + +## Page Parts + +PageComponent divides the template shown above into three parts, `title`, `breadcrumb`, `toolbar`. Each can be configured separately. + +## Usage + +Firstly, you need to import `PageModule` from `@abp/ng.components/page` as follows: + +`app.module.ts` + +```javascript +import { PageModule } from '@abp/ng.components/page'; +import { AppComponent } from './app.component'; + +@NgModule({ + declarations: [AppComponent], + imports: [PageModule] +}) +export class AppModule {} +``` + +And change the template of `app.component.ts` to the following: + +```html + +
+ +
+
+``` + +## Inputs + +* title: `string`: Will be be rendered within `h1.content-header-title`. If not provided, the parent `div` will not be rendered +* breadcrumb: `boolean`: Determines whether to render `abp-breadcrumb`. Default is `true`. +* toolbar: `any`: Will be passed into `abp-page-toolbar` component through `record` input. If your page does not contain `abp-page-toolbar`, you can simply omit this field. + +## Overriding template + +If you need to replace the template of any part, you can use following sub components. + +```html + + +
+

Custom Title

+
+
+ + +
+ +
+
+ + +
+ +
+
+
+``` + +You do not have to provide them all. You can just use which one you need to replace. These components have priority over the inputs declared above. If you use these components, you can omit the inputs. + +## PagePartDirective + +`PageModule` provides a structural directive that is used internally within `PageComponent` and can also be used externally. + +`PageComponent` employs this directive internally as follows: + +```html +
+ +
+``` + +It also can take a context input as follows: + +```html +
+ +
+``` + +```javascript +enum PageParts { + title = 'PageTitleContainerComponent', + breadcrumb = 'PageBreadcrumbContainerComponent', + toolbar = 'PageToolbarContainerComponent', +} +``` + +It's render strategy can be provided through Angular's Depedency Injection system. + +It expects a service through the `PAGE_RENDER_STRATEGY` injection token that implements the following interface. + +```javascript +interface PageRenderStrategy { + shouldRender(type?: string): boolean | Observable; + onInit?(type?: string, injector?: Injector, context?: any): void; + onDestroy?(type?: string, injector?: Injector, context?: any): void; + onContextUpdate?(change?: SimpleChange): void; +} +``` + +* `shouldRender` (required): It takes a string input named `type` and expects a `boolean` or `Observable`. +* `onInit` (optional): Will be called when the directive is initiated. Three inputs will be passed into this method. + * `type`: type of the page part + * `injector`: injector of the directive which could be used to retrieve anything from directive's DI tree. + * `context`: whatever context is available at initialization phase. +* `onDestroy` (optional): Will be called when the directive is destroyed. The parameters are the same with `onInit` +* `onContextUpdate` (optional): Will be called when the context is updated. + * `change`: changes of the `context` will be passed through this method. + +Let's see everything in action. + +```javascript +import {  + PageModule, + PageRenderStrategy, + PageParts, + PAGE_RENDER_STRATEGY +} from '@abp/ng.components/page'; +@Injectable() +export class MyPageRenderStrategy implements PageRenderStrategy { + shouldRender(type: string) { + // meaning everything but breadcrumb will be rendered + return type !== PageParts.breadcrumb && type !== 'custom-part'; + } + + /** + * shouldRender can also return an Observable which means + * an async service can be used within. + + constructor(private service: SomeAsyncService) {} + + shouldRender(type: string) { + return this.service.checkTypeAsync(type).pipe(map(val => val.isTrue())); + } + */ + + onInit(type: string, injector: Injector, context: any) { + // this method will be called in ngOnInit of the directive + } + + onDestroy(type: string, injector: Injector, context: any) { + // this method will be called in ngOnDestroy of the directive + } + + onContextUpdate?(change?: SimpleChange) { + // this method will be called everytime context is updated within the directive + } +} + +@Component({ + selector: 'app-root', + template: ` + + + + + +
+

Inner Title

+
+
+ ` +}) +export class AppComponent {} + +@NgModule({ + imports: [PageModule], + declarations: [AppComponent], + providers: [ + { + provide: PAGE_RENDER_STRATEGY, + useClass: MyPageRenderStrategy, + } + ] +}) +export class AppModule {} +``` diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index ec3341c623..a48afe8597 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -886,6 +886,15 @@ ] } ] + }, + { + "text": "Components", + "items": [ + { + "text": "Page", + "path": "UI/Angular/Page-Component.md" + } + ] } ] }, From 81ecdb45465bc9cd395a781dd78f897ee926fcd0 Mon Sep 17 00:00:00 2001 From: bnymncoskuner Date: Thu, 1 Apr 2021 11:49:31 +0300 Subject: [PATCH 02/14] docs: fix minor typos and improve page-comp docs --- docs/en/UI/Angular/Page-Component.md | 38 +++++++++++++++------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/docs/en/UI/Angular/Page-Component.md b/docs/en/UI/Angular/Page-Component.md index a019990be1..3c9e557176 100644 --- a/docs/en/UI/Angular/Page-Component.md +++ b/docs/en/UI/Angular/Page-Component.md @@ -1,8 +1,8 @@ # Page Component -ABP provides a component that wraps your content with some built-in components to recude the amount of code you need to write. +ABP provides a component that wraps your content with some built-in components to reduce the amount of code you need to write. -If the template of a component looks like as follows, you can utilize the `abp-page` components. +If the template of a component looks as follows, you can utilize the `abp-page` component. E.g. @@ -22,13 +22,21 @@ E.g.
- +
``` ## Page Parts -PageComponent divides the template shown above into three parts, `title`, `breadcrumb`, `toolbar`. Each can be configured separately. +PageComponent divides the template shown above into three parts, `title`, `breadcrumb`, `toolbar`. Each can be configured separately. There, also, is an enum exported from the package that describes each part. + +```javascript +export enum PageParts { + title = 'PageTitleContainerComponent', + breadcrumb = 'PageBreadcrumbContainerComponent', + toolbar = 'PageToolbarContainerComponent', +} +``` ## Usage @@ -65,7 +73,7 @@ And change the template of `app.component.ts` to the following: ## Overriding template -If you need to replace the template of any part, you can use following sub components. +If you need to replace the template of any part, you can use the following sub-components. ```html @@ -111,15 +119,7 @@ It also can take a context input as follows: ``` -```javascript -enum PageParts { - title = 'PageTitleContainerComponent', - breadcrumb = 'PageBreadcrumbContainerComponent', - toolbar = 'PageToolbarContainerComponent', -} -``` - -It's render strategy can be provided through Angular's Depedency Injection system. +Its render strategy can be provided through Angular's Dependency Injection system. It expects a service through the `PAGE_RENDER_STRATEGY` injection token that implements the following interface. @@ -132,11 +132,11 @@ interface PageRenderStrategy { } ``` -* `shouldRender` (required): It takes a string input named `type` and expects a `boolean` or `Observable`. +* `shouldRender` (required): It takes a string input named `type` and expects a `boolean` or `Observable` in return. * `onInit` (optional): Will be called when the directive is initiated. Three inputs will be passed into this method. * `type`: type of the page part * `injector`: injector of the directive which could be used to retrieve anything from directive's DI tree. - * `context`: whatever context is available at initialization phase. + * `context`: whatever context is available at the initialization phase. * `onDestroy` (optional): Will be called when the directive is destroyed. The parameters are the same with `onInit` * `onContextUpdate` (optional): Will be called when the context is updated. * `change`: changes of the `context` will be passed through this method. @@ -153,7 +153,7 @@ import {  @Injectable() export class MyPageRenderStrategy implements PageRenderStrategy { shouldRender(type: string) { - // meaning everything but breadcrumb will be rendered + // meaning everything but breadcrumb and custom-part will be rendered return type !== PageParts.breadcrumb && type !== 'custom-part'; } @@ -209,3 +209,7 @@ export class AppComponent {} }) export class AppModule {} ``` + +## See Also + +- [Page Toolbar Extensions for Angular UI](./Page-Page-Toolbar-Extensions.md) From e99858ce404b6b8b0933b20a9c8b909505b33a65 Mon Sep 17 00:00:00 2001 From: bnymncoskuner Date: Mon, 5 Apr 2021 11:08:23 +0300 Subject: [PATCH 03/14] refactor: remove empty div if nothing is used in page-comp --- .../packages/components/page/src/page.component.html | 2 +- .../packages/components/page/src/page.component.ts | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/npm/ng-packs/packages/components/page/src/page.component.html b/npm/ng-packs/packages/components/page/src/page.component.html index 71715fd82e..fe5aff2e58 100644 --- a/npm/ng-packs/packages/components/page/src/page.component.html +++ b/npm/ng-packs/packages/components/page/src/page.component.html @@ -1,4 +1,4 @@ -
+
diff --git a/npm/ng-packs/packages/components/page/src/page.component.ts b/npm/ng-packs/packages/components/page/src/page.component.ts index 49e884fb2c..24b6d18ccf 100644 --- a/npm/ng-packs/packages/components/page/src/page.component.ts +++ b/npm/ng-packs/packages/components/page/src/page.component.ts @@ -37,4 +37,15 @@ export class PageComponent { @ContentChild(PageBreadcrumbContainerComponent) customBreadcrumb: PageBreadcrumbContainerComponent; @ContentChild(PageToolbarContainerComponent) customToolbar: PageToolbarContainerComponent; + + get shouldRenderRow() { + return !!( + this.title || + this.toolbarVisible || + this.breadcrumbVisible || + this.customTitle || + this.customBreadcrumb || + this.customToolbar + ); + } } From 2a1c58fdcbeb4963e7afd9de72ce400b918c1dab Mon Sep 17 00:00:00 2001 From: bnymncoskuner Date: Mon, 5 Apr 2021 11:08:34 +0300 Subject: [PATCH 04/14] docs: improve page-component docs --- docs/en/UI/Angular/Page-Component.md | 41 +++++++++++++++------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/docs/en/UI/Angular/Page-Component.md b/docs/en/UI/Angular/Page-Component.md index 3c9e557176..a9e9857142 100644 --- a/docs/en/UI/Angular/Page-Component.md +++ b/docs/en/UI/Angular/Page-Component.md @@ -4,14 +4,14 @@ ABP provides a component that wraps your content with some built-in components t If the template of a component looks as follows, you can utilize the `abp-page` component. -E.g. +Let's look at the following example without `abp-page` component. -`app.component.ts` +`dashboard.component.ts` ```html
-

{{ '::AppTitle' | abpLocalization }}

+

{{ '::Dashboard' | abpLocalization }}

-
- +
+
``` @@ -36,30 +36,32 @@ export enum PageParts { breadcrumb = 'PageBreadcrumbContainerComponent', toolbar = 'PageToolbarContainerComponent', } + +// You can import this enum from -> import { PageParts } from '@abp/ng.components/page'; ``` ## Usage Firstly, you need to import `PageModule` from `@abp/ng.components/page` as follows: -`app.module.ts` +`dashboard.module.ts` ```javascript import { PageModule } from '@abp/ng.components/page'; -import { AppComponent } from './app.component'; +import { DashboardComponent } from './dashboard.component'; @NgModule({ - declarations: [AppComponent], + declarations: [DashboardComponent], imports: [PageModule] }) -export class AppModule {} +export class DashboardModule {} ``` -And change the template of `app.component.ts` to the following: +And change the template of `dashboard.component.ts` to the following: ```html - -
+ +
@@ -150,6 +152,7 @@ import {  PageParts, PAGE_RENDER_STRATEGY } from '@abp/ng.components/page'; + @Injectable() export class MyPageRenderStrategy implements PageRenderStrategy { shouldRender(type: string) { @@ -182,24 +185,24 @@ export class MyPageRenderStrategy implements PageRenderStrategy { } @Component({ - selector: 'app-root', + selector: 'app-dashboard', template: ` - + - + -
+

Inner Title

` }) -export class AppComponent {} +export class DashboardComponent {} @NgModule({ imports: [PageModule], - declarations: [AppComponent], + declarations: [DashboardComponent], providers: [ { provide: PAGE_RENDER_STRATEGY, @@ -207,7 +210,7 @@ export class AppComponent {} } ] }) -export class AppModule {} +export class DashboardModule {} ``` ## See Also From 328e8b19db0cbc3ce6869380fe91bf5827b63588 Mon Sep 17 00:00:00 2001 From: Ahmet Date: Mon, 5 Apr 2021 12:37:25 +0300 Subject: [PATCH 05/14] use IRemoteStreamContent for media uploading --- .../CreateMediaInputWithStream.cs | 16 +++++++++++ .../IMediaDescriptorAdminAppService.cs | 2 +- .../MediaDescriptorAdminAppService.cs | 10 +++---- .../CmsKit/Admin/CmsKitAdminHttpApiModule.cs | 10 +++++++ .../MediaDescriptorAdminController.cs | 27 +++---------------- .../MediaDescriptorAdminAppService_Tests.cs | 13 ++++----- 6 files changed, 41 insertions(+), 37 deletions(-) create mode 100644 modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/MediaDescriptors/CreateMediaInputWithStream.cs diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/MediaDescriptors/CreateMediaInputWithStream.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/MediaDescriptors/CreateMediaInputWithStream.cs new file mode 100644 index 0000000000..a8a13b2ed2 --- /dev/null +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/MediaDescriptors/CreateMediaInputWithStream.cs @@ -0,0 +1,16 @@ +using System.ComponentModel.DataAnnotations; +using Volo.Abp.Content; +using Volo.Abp.Validation; +using Volo.CmsKit.MediaDescriptors; + +namespace Volo.CmsKit.Admin.MediaDescriptors +{ + public class CreateMediaInputWithStream + { + [Required] + [DynamicStringLength(typeof(MediaDescriptorConsts), nameof(MediaDescriptorConsts.MaxNameLength))] + public string Name { get; set; } + + public IRemoteStreamContent File { get; set; } + } +} \ No newline at end of file diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/MediaDescriptors/IMediaDescriptorAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/MediaDescriptors/IMediaDescriptorAdminAppService.cs index eb4819dd06..83cd14e90c 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/MediaDescriptors/IMediaDescriptorAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application.Contracts/Volo/CmsKit/Admin/MediaDescriptors/IMediaDescriptorAdminAppService.cs @@ -6,7 +6,7 @@ namespace Volo.CmsKit.Admin.MediaDescriptors { public interface IMediaDescriptorAdminAppService : IApplicationService { - Task CreateAsync(CreateMediaInputStream inputStream); + Task CreateAsync(string entityType, CreateMediaInputWithStream inputStream); Task DeleteAsync(Guid id); } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/MediaDescriptors/MediaDescriptorAdminAppService.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/MediaDescriptors/MediaDescriptorAdminAppService.cs index b359d55244..fa799cb65b 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/MediaDescriptors/MediaDescriptorAdminAppService.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.Application/Volo/CmsKit/Admin/MediaDescriptors/MediaDescriptorAdminAppService.cs @@ -1,11 +1,9 @@ using System; using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; using Volo.Abp.BlobStoring; using Volo.Abp.GlobalFeatures; using Volo.CmsKit.GlobalFeatures; using Volo.CmsKit.MediaDescriptors; -using Volo.CmsKit.Permissions; namespace Volo.CmsKit.Admin.MediaDescriptors { @@ -29,16 +27,16 @@ namespace Volo.CmsKit.Admin.MediaDescriptors MediaDescriptorDefinitionStore = mediaDescriptorDefinitionStore; } - public virtual async Task CreateAsync(CreateMediaInputStream inputStream) + public virtual async Task CreateAsync(string entityType, CreateMediaInputWithStream inputStream) { - var definition = await MediaDescriptorDefinitionStore.GetAsync(inputStream.EntityType); + var definition = await MediaDescriptorDefinitionStore.GetAsync(entityType); /* TODO: Shouldn't CreatePolicies be a dictionary and we check for inputStream.EntityType? */ await CheckAnyOfPoliciesAsync(definition.CreatePolicies); - using (var stream = inputStream.GetStream()) + using (var stream = inputStream.File.GetStream()) { - var newEntity = await MediaDescriptorManager.CreateAsync(inputStream.EntityType, inputStream.Name, inputStream.ContentType, inputStream.ContentLength ?? 0); + var newEntity = await MediaDescriptorManager.CreateAsync(entityType, inputStream.Name, inputStream.File.ContentType, inputStream.File.ContentLength ?? 0); await MediaContainer.SaveAsync(newEntity.Id.ToString(), stream); await MediaDescriptorRepository.InsertAsync(newEntity); diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/CmsKitAdminHttpApiModule.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/CmsKitAdminHttpApiModule.cs index 5d84242bcd..bb573d55e6 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/CmsKitAdminHttpApiModule.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/CmsKitAdminHttpApiModule.cs @@ -1,5 +1,7 @@ using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.Modularity; +using Volo.CmsKit.Admin.MediaDescriptors; namespace Volo.CmsKit.Admin { @@ -16,5 +18,13 @@ namespace Volo.CmsKit.Admin mvcBuilder.AddApplicationPartIfNotExists(typeof(CmsKitAdminHttpApiModule).Assembly); }); } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.ConventionalControllers.FormBodyBindingIgnoredTypes.Add(typeof(CreateMediaInputWithStream)); + }); + } } } diff --git a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/MediaDescriptors/MediaDescriptorAdminController.cs b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/MediaDescriptors/MediaDescriptorAdminController.cs index da84dc8a3d..07c1315eed 100644 --- a/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/MediaDescriptors/MediaDescriptorAdminController.cs +++ b/modules/cms-kit/src/Volo.CmsKit.Admin.HttpApi/Volo/CmsKit/Admin/MediaDescriptors/MediaDescriptorAdminController.cs @@ -25,10 +25,10 @@ namespace Volo.CmsKit.Admin.MediaDescriptors } [HttpPost] - [NonAction] - public virtual Task CreateAsync(CreateMediaInputStream inputStream) + [Route("{entityType}")] + public virtual Task CreateAsync(string entityType, CreateMediaInputWithStream inputStream) { - return MediaDescriptorAdminAppService.CreateAsync(inputStream); + return MediaDescriptorAdminAppService.CreateAsync(entityType, inputStream); } [HttpDelete] @@ -37,26 +37,5 @@ namespace Volo.CmsKit.Admin.MediaDescriptors { return MediaDescriptorAdminAppService.DeleteAsync(id); } - - [HttpPost] - [Route("{entityType}")] - public virtual async Task UploadAsync(string entityType, IFormFile file) - { - if (file == null) - { - return BadRequest(); - } - - var inputStream = new CreateMediaInputStream(file.OpenReadStream()) - { - EntityType = entityType, - ContentType = file.ContentType, - Name = file.FileName - }; - - var mediaDescriptorDto = await MediaDescriptorAdminAppService.CreateAsync(inputStream); - - return StatusCode((int)HttpStatusCode.Created, mediaDescriptorDto); - } } } \ No newline at end of file diff --git a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/MediaDescriptors/MediaDescriptorAdminAppService_Tests.cs b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/MediaDescriptors/MediaDescriptorAdminAppService_Tests.cs index 52169eddbe..38a8b472bd 100644 --- a/modules/cms-kit/test/Volo.CmsKit.Application.Tests/MediaDescriptors/MediaDescriptorAdminAppService_Tests.cs +++ b/modules/cms-kit/test/Volo.CmsKit.Application.Tests/MediaDescriptors/MediaDescriptorAdminAppService_Tests.cs @@ -3,6 +3,7 @@ using System.IO; using System.Text; using System.Threading.Tasks; using Shouldly; +using Volo.Abp.Content; using Volo.CmsKit.Admin.MediaDescriptors; using Xunit; @@ -31,14 +32,14 @@ namespace Volo.CmsKit.MediaDescriptors using var stream = new MemoryStream(Encoding.UTF8.GetBytes(mediaContent)); - var inputStream = new CreateMediaInputStream(stream) + var media = await _mediaDescriptorAdminAppService.CreateAsync(_cmsKitTestData.Media_1_EntityType, new CreateMediaInputWithStream { - ContentType = mediaType, Name = mediaName, - EntityType = _cmsKitTestData.Media_1_EntityType - }; - - var media = await _mediaDescriptorAdminAppService.CreateAsync(inputStream); + File = new RemoteStreamContent(stream) + { + ContentType = mediaType + } + }); media.ShouldNotBeNull(); } From 96519097693f2e1bf31095a8f0ca086505dbec55 Mon Sep 17 00:00:00 2001 From: bnymncoskuner Date: Mon, 5 Apr 2021 13:32:25 +0300 Subject: [PATCH 06/14] feat: add abpClose directive to modal --- .../theme-shared/src/lib/components/index.ts | 1 + .../components/modal/modal-close.directive.ts | 16 ++++++++++++++++ .../theme-shared/src/lib/theme-shared.module.ts | 2 ++ 3 files changed, 19 insertions(+) create mode 100644 npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal-close.directive.ts diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/index.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/index.ts index 608dbb8ba8..a80a7cb574 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/index.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/index.ts @@ -6,6 +6,7 @@ export * from './http-error-wrapper/http-error-wrapper.component'; export * from './loader-bar/loader-bar.component'; export * from './loading/loading.component'; export * from './modal/modal.component'; +export * from './modal/modal-close.directive'; export * from './sort-order-icon/sort-order-icon.component'; export * from './table-empty-message/table-empty-message.component'; export * from './table/table.component'; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal-close.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal-close.directive.ts new file mode 100644 index 0000000000..a20c8d8a34 --- /dev/null +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal-close.directive.ts @@ -0,0 +1,16 @@ +import { Directive, HostListener, Optional } from '@angular/core'; +import { ModalComponent } from './modal.component'; + +@Directive({ selector: '[abpClose]' }) +export class ModalCloseDirective { + constructor(@Optional() private modal: ModalComponent) { + if (!modal) { + console.error('Please use abpClose within an abp-modal'); + } + } + + @HostListener('click') + onClick() { + this.modal?.close(); + } +} diff --git a/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts b/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts index 8d8f08ea6b..ddf1d6a5a3 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts @@ -37,6 +37,7 @@ import { THEME_SHARED_ROUTE_PROVIDERS } from './providers/route.provider'; import { THEME_SHARED_APPEND_CONTENT } from './tokens/append-content.token'; import { HTTP_ERROR_CONFIG, httpErrorConfigFactory } from './tokens/http-error.token'; import { DateParserFormatter } from './utils/date-parser-formatter'; +import { ModalCloseDirective } from './components/modal/modal-close.directive'; const declarationsWithExports = [ BreadcrumbComponent, @@ -55,6 +56,7 @@ const declarationsWithExports = [ NgxDatatableListDirective, LoadingDirective, TableSortDirective, + ModalCloseDirective, ]; @NgModule({ From 2aa6193bf4faf83787d2b71c4d08f36b80983c85 Mon Sep 17 00:00:00 2001 From: bnymncoskuner Date: Mon, 5 Apr 2021 13:35:54 +0300 Subject: [PATCH 07/14] chore: deprecate abpClose template directive --- .../src/lib/components/modal/modal.component.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts index d1414d0272..d11d1bcbc2 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts @@ -78,6 +78,9 @@ export class ModalComponent implements OnDestroy { @ContentChild(ButtonComponent, { static: false, read: ButtonComponent }) abpSubmit: ButtonComponent; + /** + * @deprecated will be removed in v5.0 + */ @ContentChild('abpClose', { static: false, read: ElementRef }) abpClose: ElementRef; @@ -203,6 +206,9 @@ export class ModalComponent implements OnDestroy { setTimeout(() => { if (!this.abpClose) return; + console.warn( + 'Please use abpClose directive instead of #abpClose template variable. #abpClose will be removed in v5.0', + ); fromEvent(this.abpClose.nativeElement, 'click') .pipe(takeUntil(this.destroy$)) .subscribe(() => this.close()); From 3af9576ba8fd233f7a6ecdb918bb9ac7eb29e863 Mon Sep 17 00:00:00 2001 From: bnymncoskuner Date: Mon, 5 Apr 2021 13:38:51 +0300 Subject: [PATCH 08/14] docs: replace #abpClose with abpClose directive --- docs/en/Tutorials/Part-3.md | 4 ++-- docs/en/Tutorials/Part-9.md | 2 +- docs/en/UI/Angular/Entity-Action-Extensions.md | 2 +- .../How-Replaceable-Components-Work-with-Extensions.md | 2 +- .../UI/Angular/Permission-Management-Component-Replacement.md | 2 +- docs/pt-BR/Tutorials/Angular/Part-II.md | 4 ++-- docs/zh-Hans/Tutorials/Part-3.md | 4 ++-- .../UI/Angular/Permission-Management-Component-Replacement.md | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/en/Tutorials/Part-3.md b/docs/en/Tutorials/Part-3.md index 41c4781421..03daab1843 100644 --- a/docs/en/Tutorials/Part-3.md +++ b/docs/en/Tutorials/Part-3.md @@ -709,7 +709,7 @@ Open `/src/app/book/book.component.html` and make the following changes: - @@ -844,7 +844,7 @@ Also replace ` ` with the following code p ````html - diff --git a/docs/en/Tutorials/Part-9.md b/docs/en/Tutorials/Part-9.md index 55c077bd9c..1fb4d0e703 100644 --- a/docs/en/Tutorials/Part-9.md +++ b/docs/en/Tutorials/Part-9.md @@ -792,7 +792,7 @@ Open the `/src/app/author/author.component.html` and replace the content as belo - diff --git a/docs/en/UI/Angular/Entity-Action-Extensions.md b/docs/en/UI/Angular/Entity-Action-Extensions.md index fd22e293fd..1ee0a3b70a 100644 --- a/docs/en/UI/Angular/Entity-Action-Extensions.md +++ b/docs/en/UI/Angular/Entity-Action-Extensions.md @@ -180,7 +180,7 @@ Let's employ dependency injection to extend the functionality of `IdentityModule - diff --git a/docs/en/UI/Angular/How-Replaceable-Components-Work-with-Extensions.md b/docs/en/UI/Angular/How-Replaceable-Components-Work-with-Extensions.md index d942975646..147f8010a6 100644 --- a/docs/en/UI/Angular/How-Replaceable-Components-Work-with-Extensions.md +++ b/docs/en/UI/Angular/How-Replaceable-Components-Work-with-Extensions.md @@ -215,7 +215,7 @@ Open the generated `src/app/my-role/my-role.component.html` file and replace its - {%{{{ diff --git a/docs/en/UI/Angular/Permission-Management-Component-Replacement.md b/docs/en/UI/Angular/Permission-Management-Component-Replacement.md index 9ae712cedd..b6fcef3bb9 100644 --- a/docs/en/UI/Angular/Permission-Management-Component-Replacement.md +++ b/docs/en/UI/Angular/Permission-Management-Component-Replacement.md @@ -459,7 +459,7 @@ Open the generated `permission-management.component.html` in `src/app/permission
- {%{{{ diff --git a/docs/pt-BR/Tutorials/Angular/Part-II.md b/docs/pt-BR/Tutorials/Angular/Part-II.md index b75fa9e21c..b4b86350b0 100644 --- a/docs/pt-BR/Tutorials/Angular/Part-II.md +++ b/docs/pt-BR/Tutorials/Angular/Part-II.md @@ -90,7 +90,7 @@ Abra o `book-list.component.html`e adicione o `abp-modal`para mostrar / ocultar - @@ -276,7 +276,7 @@ Abra o `book-list.component.html`e adicione um `abp-button`para salvar o formul ```html - @@ -859,7 +859,7 @@ export class BookComponent implements OnInit { ````html - diff --git a/docs/zh-Hans/UI/Angular/Permission-Management-Component-Replacement.md b/docs/zh-Hans/UI/Angular/Permission-Management-Component-Replacement.md index 0b1f71035e..3ea2db6f51 100644 --- a/docs/zh-Hans/UI/Angular/Permission-Management-Component-Replacement.md +++ b/docs/zh-Hans/UI/Angular/Permission-Management-Component-Replacement.md @@ -459,7 +459,7 @@ function getPermissions(groups: PermissionManagement.Group[]): PermissionManagem
- {%{{{ From 43aff2118e925b0a5c681066e8254c9b8b96372e Mon Sep 17 00:00:00 2001 From: bnymncoskuner Date: Mon, 5 Apr 2021 13:40:07 +0300 Subject: [PATCH 09/14] docs: update modal doc with abpClose directive --- docs/en/UI/Angular/Modal.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/en/UI/Angular/Modal.md b/docs/en/UI/Angular/Modal.md index f1583d4813..144f38e842 100644 --- a/docs/en/UI/Angular/Modal.md +++ b/docs/en/UI/Angular/Modal.md @@ -6,7 +6,7 @@ The `abp-modal` provides some additional benefits: - It is **flexible**. You can pass header, body, footer templates easily by adding the templates to the `abp-modal` content. It can also be implemented quickly. - Provides several inputs be able to customize the modal and several outputs be able to listen to some events. - - Automatically detects the close button which has a `#abpClose` template variable and closes the modal when pressed this button. + - Automatically detects the close button which has a `abpClose` directive attached to and closes the modal when pressed this button. - Automatically detects the `abp-button` and triggers its loading spinner when the `busy` input value of the modal component is true. - Automatically checks if the form inside the modal **has changed, but not saved**. It warns the user by displaying a [confirmation popup](Confirmation-Service) in this case when a user tries to close the modal or refresh/close the tab of the browser. @@ -47,7 +47,7 @@ You can add the `abp-modal` to your component very quickly. See an example: - + ``` @@ -116,7 +116,7 @@ See an example form inside a modal: - From 3a8a32d6c8cc79ac40a8413931ee649e92dd71ce Mon Sep 17 00:00:00 2001 From: bnymncoskuner Date: Mon, 5 Apr 2021 14:21:57 +0300 Subject: [PATCH 10/14] refactor: replace #abpClose with the directive --- .../src/lib/components/tenant-box/tenant-box.component.html | 4 ++-- .../feature-management/feature-management.component.html | 6 +++--- .../identity/src/lib/components/roles/roles.component.html | 2 +- .../identity/src/lib/components/users/users.component.html | 2 +- .../src/lib/components/permission-management.component.html | 2 +- .../src/lib/components/tenants/tenants.component.html | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/npm/ng-packs/packages/account/src/lib/components/tenant-box/tenant-box.component.html b/npm/ng-packs/packages/account/src/lib/components/tenant-box/tenant-box.component.html index e8b2df61e1..91e68d9a0a 100644 --- a/npm/ng-packs/packages/account/src/lib/components/tenant-box/tenant-box.component.html +++ b/npm/ng-packs/packages/account/src/lib/components/tenant-box/tenant-box.component.html @@ -3,7 +3,7 @@
- {{ + {{ 'AbpUiMultiTenancy::Tenant' | abpLocalization }}
@@ -47,7 +47,7 @@ - + }} + - - {{ diff --git a/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html b/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html index 97d0616eb3..aa6dac1e93 100644 --- a/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html +++ b/npm/ng-packs/packages/identity/src/lib/components/users/users.component.html @@ -74,7 +74,7 @@ - {{ diff --git a/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.html b/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.html index 148b4ab1b5..06ab7ff9f1 100644 --- a/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.html +++ b/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.html @@ -94,7 +94,7 @@
- {{ diff --git a/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html b/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html index a418e9ff1d..c296589afd 100644 --- a/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html +++ b/npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html @@ -40,7 +40,7 @@ - {{ From 2667ffffaf5d0586ae400f375d947af73d68de39 Mon Sep 17 00:00:00 2001 From: bnymncoskuner Date: Mon, 5 Apr 2021 14:22:27 +0300 Subject: [PATCH 11/14] test: update modal test with the directive --- .../src/lib/tests/modal.component.spec.ts | 2 +- npm/ng-packs/yarn.lock | 117 ++++++++++-------- 2 files changed, 68 insertions(+), 51 deletions(-) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/modal.component.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/modal.component.spec.ts index 7c693211f1..60c71b8e16 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/modal.component.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/modal.component.spec.ts @@ -51,7 +51,7 @@ describe('ModalComponent', () => { diff --git a/npm/ng-packs/yarn.lock b/npm/ng-packs/yarn.lock index 11cb8c5e9e..7d33c0fc27 100644 --- a/npm/ng-packs/yarn.lock +++ b/npm/ng-packs/yarn.lock @@ -2,12 +2,20 @@ # yarn lockfile v1 -"@abp/ng.core@~4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@abp/ng.core/-/ng.core-4.2.2.tgz#2b0b2d210bd124e4aaab3560763f36d38b24c63f" - integrity sha512-G2d5tcFgvmeLNP9JxlU6L3ywMqFdGBwdG5hTzyVxkE3qpiSfzCPCrMVcCh4SnOxm+Qo7kEXtT3xDv6b+Ye2uTQ== +"@abp/ng.components@~4.3.0-rc.1": + version "4.3.0-rc.1" + resolved "https://registry.yarnpkg.com/@abp/ng.components/-/ng.components-4.3.0-rc.1.tgz#7142e476577fe74429b0eb0f0f9af5955a3aea3f" + integrity sha512-JjRRbE9RHh8X82PKLO1VKsEMui+mCNzGgkmBVL1qwTrlLcfUW6IYjCVXUxQX67e6waHVT+cIFFWWk00zfVEMJw== + dependencies: + ng-zorro-antd "^11.0.0" + tslib "^2.0.0" + +"@abp/ng.core@~4.3.0-rc.1": + version "4.3.0-rc.1" + resolved "https://registry.yarnpkg.com/@abp/ng.core/-/ng.core-4.3.0-rc.1.tgz#8cd396fcdbeff3ad71ff4a3ce175395fdaf0cca4" + integrity sha512-9ydmdginW0f4g9ZlAF78q2RUvHhGBr0Aj5cN/sAnD+ohNDkYeSd42szqJAkoktEfTw4yHEFC+kKJLELAhRgChg== dependencies: - "@abp/utils" "^4.2.1" + "@abp/utils" "^4.2.2" "@angular/localize" "~10.0.10" "@ngxs/store" "^3.7.0" angular-oauth2-oidc "^10.0.0" @@ -17,88 +25,97 @@ ts-toolbelt "6.15.4" tslib "^2.0.0" -"@abp/ng.feature-management@~4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@abp/ng.feature-management/-/ng.feature-management-4.2.2.tgz#694f6d6e391d5688b0cbca3ed6e9b80e24cac37f" - integrity sha512-KvE4sRPpQRrg3y03hO/2y6LUDPSaHJGm7pyEb0vwv4728RTMoR1cFwGiu8o2uRxslApq3O6EM3DvKY+6F0VNSw== +"@abp/ng.feature-management@~4.3.0-rc.1": + version "4.3.0-rc.1" + resolved "https://registry.yarnpkg.com/@abp/ng.feature-management/-/ng.feature-management-4.3.0-rc.1.tgz#d4a3536add0901851f035a3c1e591e6f3bbaa6fc" + integrity sha512-PH5X7D2L+tyhCqEBTLxOVFToJvdgalvxGWWxiTHT+0GwN9yKNy4cmot4WM7U2iRG9DjwpNKhQSEwqjRM1hxc/Q== dependencies: - "@abp/ng.theme.shared" "~4.2.2" + "@abp/ng.theme.shared" "~4.3.0-rc.1" tslib "^2.0.0" -"@abp/ng.identity@~4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@abp/ng.identity/-/ng.identity-4.2.2.tgz#640065e823fd6e9430711d499084f04779c2e990" - integrity sha512-gbkY2hL21OjzsZwZCwqhxBT8xndFIVU8SD9qAYAv6XlIGUuIwIy/VLSuU/hFF0+8qg0TdU359aH1F6FtwSm+/g== +"@abp/ng.identity@~4.3.0-rc.1": + version "4.3.0-rc.1" + resolved "https://registry.yarnpkg.com/@abp/ng.identity/-/ng.identity-4.3.0-rc.1.tgz#ffe6644e876f8998e3e6dff110e5d1c8461a6c71" + integrity sha512-F5pGGVOUYKK+vLAE87u+rYlRGhrlTfYlme9gwHgXW8sElrdSPe03Q63kXap9e/w/foeqe/C6PLBrZ255K2BtwQ== dependencies: - "@abp/ng.permission-management" "~4.2.2" - "@abp/ng.theme.shared" "~4.2.2" + "@abp/ng.permission-management" "~4.3.0-rc.1" + "@abp/ng.theme.shared" "~4.3.0-rc.1" tslib "^2.0.0" -"@abp/ng.permission-management@~4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@abp/ng.permission-management/-/ng.permission-management-4.2.2.tgz#a63a25bbe48c0044630af430b7674c5d040a5999" - integrity sha512-c1C8O73oqRf3NCSXMvECayzvjTx+nEGnh3KX7IWtNMr0/GIUCokzH9yX2Cd8uZPYINvlZTOLu73ImrIjTllJ/w== +"@abp/ng.permission-management@~4.3.0-rc.1": + version "4.3.0-rc.1" + resolved "https://registry.yarnpkg.com/@abp/ng.permission-management/-/ng.permission-management-4.3.0-rc.1.tgz#9fe9fbb2a5a4306ff549ed0f00bf9a47fb7a3f49" + integrity sha512-5LVC22bukBWD6r1kMZD8ooq0dr8k9AjpdGk/vcdC/86l8oOlqbaarrGiFawSabFIZqjglC6cZ0V4lEymRxhNQQ== dependencies: - "@abp/ng.theme.shared" "~4.2.2" + "@abp/ng.theme.shared" "~4.3.0-rc.1" tslib "^2.0.0" -"@abp/ng.schematics@~4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@abp/ng.schematics/-/ng.schematics-4.2.2.tgz#757a638fe01f4816f74742551f8b304d55aa5bc0" - integrity sha512-1YRMg1Hex+6CigDs68fXCe48SU/f8kYSkhLWGs2ZiYJeo00Cv5Sd+Vo8ZbRzuC04w4JQlI0U6jCgZfcbf7eehQ== +"@abp/ng.schematics@~4.3.0-rc.1": + version "4.3.0-rc.1-1" + resolved "https://registry.yarnpkg.com/@abp/ng.schematics/-/ng.schematics-4.3.0-rc.1-1.tgz#70897e5be3ea308b1a535241ddbf08ad730be1cf" + integrity sha512-YKnsx4q4OrUBJl8VbzHORlnPT1iEv6y72soe/xWqasL8i1UIEAUQjLx7ZDZCMWq+Dm+v7EgMU/yOjcNpdL3Eng== dependencies: "@angular-devkit/core" "~11.0.2" "@angular-devkit/schematics" "~11.0.2" got "^11.5.2" jsonc-parser "^2.3.0" + should-quote "^1.0.0" typescript "~3.9.2" -"@abp/ng.setting-management@~4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@abp/ng.setting-management/-/ng.setting-management-4.2.2.tgz#f92040222d29e84b31b074c23fe0233c344a705e" - integrity sha512-hm/kuday+L32hqvvFCjNGEhmOwZSK8X+h1l8v8xaSA7JaP82pqBKARtUjumey6v52UiL/mDj/p89M+E9PryD5w== +"@abp/ng.setting-management@~4.3.0-rc.1": + version "4.3.0-rc.1" + resolved "https://registry.yarnpkg.com/@abp/ng.setting-management/-/ng.setting-management-4.3.0-rc.1.tgz#d157eb62c5b34675a5cb40090b87ace318e2aacd" + integrity sha512-8aA7ixn5sKk9jgW9cGoGRWAmHL5D7As5E7aBxddTIxlvIIChc9A7xF8GigD+WufOHoKEFKRxHmEzDtnpTS0Hqg== dependencies: - "@abp/ng.theme.shared" "~4.2.2" + "@abp/ng.components" "~4.3.0-rc.1" + "@abp/ng.theme.shared" "~4.3.0-rc.1" tslib "^2.0.0" -"@abp/ng.tenant-management@~4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@abp/ng.tenant-management/-/ng.tenant-management-4.2.2.tgz#91fa26176a9019bde52e4a8652e77a0f8394d0d7" - integrity sha512-/5yDzIKK0lokyy7vddIIsmM3fcXkxA9pOMMZYOIMchOTQkUnqQ6Gfo53iCRrt8UgIYIzEd1eY0fObHhwKu33yA== +"@abp/ng.tenant-management@~4.3.0-rc.1": + version "4.3.0-rc.1" + resolved "https://registry.yarnpkg.com/@abp/ng.tenant-management/-/ng.tenant-management-4.3.0-rc.1.tgz#72f9d62868ba50ad7ae30964ff3f28b50ef89b4e" + integrity sha512-/Z1qED1BEx1vkR/N1qPeE+OqE/HXksHrl3v4bPjKMy1k6HGorzfzaBXghpwumvwGcAOLXGgigJAkG7bBr6qlrA== dependencies: - "@abp/ng.feature-management" "~4.2.2" - "@abp/ng.theme.shared" "~4.2.2" + "@abp/ng.feature-management" "~4.3.0-rc.1" + "@abp/ng.theme.shared" "~4.3.0-rc.1" tslib "^2.0.0" -"@abp/ng.theme.basic@~4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@abp/ng.theme.basic/-/ng.theme.basic-4.2.2.tgz#87e349365a3cec93ab19364d29e6f22a58650371" - integrity sha512-tKCviHib50Eal7n/pUDVU/HtCfEP+BO7ys/SQFY5+TZrIQwUMsI9r6RhHVZGtHzvmwFXzT8r03IqKrpjZjfjSg== +"@abp/ng.theme.basic@~4.3.0-rc.1": + version "4.3.0-rc.1" + resolved "https://registry.yarnpkg.com/@abp/ng.theme.basic/-/ng.theme.basic-4.3.0-rc.1.tgz#f9d1cdaff4f64fa1b1e79b288a4780f99dd70989" + integrity sha512-E+cALwuHHjg32kPR/dd/4rHrLc+pv4BSV+SH0RmdVPhbmbQBDCzz5YOCmss1p7KFSlGWF4+pUVn9ev4I+yYFhA== dependencies: - "@abp/ng.theme.shared" "~4.2.2" + "@abp/ng.theme.shared" "~4.3.0-rc.1" tslib "^2.0.0" -"@abp/ng.theme.shared@~4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@abp/ng.theme.shared/-/ng.theme.shared-4.2.2.tgz#c8e19884e29f286323ae9dd1ffa1d7b4e3584971" - integrity sha512-qq+/klJywoy/Pr2dW0gM0jb2ac2qnZAYuUKhkV+wp+xMgZV2PW24V7mHbpPwtzg5ClQnLLyBYuj7S5qHblXRiw== +"@abp/ng.theme.shared@~4.3.0-rc.1": + version "4.3.0-rc.1" + resolved "https://registry.yarnpkg.com/@abp/ng.theme.shared/-/ng.theme.shared-4.3.0-rc.1.tgz#1442443baf2a70832f0bd0f04a2103a731b7b521" + integrity sha512-1Ht2lKkenFQYrMxIaebiRmYhv8ASZEM/QFaEVak5u5C9KCVxC9sFX1Dl+MgFY11hoxiEbbI0GiXT+TfjAOmuVw== dependencies: - "@abp/ng.core" "~4.2.2" + "@abp/ng.core" "~4.3.0-rc.1" "@fortawesome/fontawesome-free" "^5.14.0" "@ng-bootstrap/ng-bootstrap" "^7.0.0" "@ngx-validate/core" "^0.0.13" "@swimlane/ngx-datatable" "^17.1.0" - bootstrap "^4.5.0" + bootstrap "~4.6.0" chart.js "^2.9.3" tslib "^2.0.0" -"@abp/utils@^4.2.1", "@abp/utils@^4.2.2": +"@abp/utils@^4.2.2": version "4.2.2" resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-4.2.2.tgz#7afdbbd14246ce06c074109c51d01588596805a9" integrity sha512-fyPCe5BcS8b88qQd8Ns1D65TdlaOoOryL7mgkYAwBTTpmADLNJQ7R2L4VZxDybkMN2lou+ckCx7qlFIlQmWa7g== dependencies: just-compare "^1.3.0" +"@abp/utils@^4.3.0-rc.1": + version "4.3.0-rc.1" + resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-4.3.0-rc.1.tgz#82ef26e01e0cb38417bf4fa9459fde85cbc2b424" + integrity sha512-C/sk6jZQDENI7FbylBoPnTb1rC5eVPnsL8B++vAH4jS//OAj2iNvE6tCewK21GYI/JmfmQzzauQBzOiOJR9a6A== + dependencies: + just-compare "^1.3.0" + "@angular-builders/jest@^10.0.0": version "10.0.1" resolved "https://registry.yarnpkg.com/@angular-builders/jest/-/jest-10.0.1.tgz#a1a6fb5d11b5d54c051bdaa2012b5f046371560c" @@ -3968,7 +3985,7 @@ boolbase@^1.0.0, boolbase@~1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= -bootstrap@^4.5.0: +bootstrap@^4.5.0, bootstrap@~4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.6.0.tgz#97b9f29ac98f98dfa43bf7468262d84392552fd7" integrity sha512-Io55IuQY3kydzHtbGvQya3H+KorS/M9rSNyfCGCg9WZ4pyT/lCxIlpJgG1GXW/PswzC84Tr2fBYi+7+jFVQQBw== @@ -9832,7 +9849,7 @@ ng-packagr@^11.0.1: sync-rpc "^1.3.6" terser "^5.5.1" -ng-zorro-antd@^11.0.1: +ng-zorro-antd@^11.0.0, ng-zorro-antd@^11.0.1: version "11.3.0" resolved "https://registry.yarnpkg.com/ng-zorro-antd/-/ng-zorro-antd-11.3.0.tgz#c09c6c34229bad3cdb22a64b4806f898053f7bb3" integrity sha512-6oX+DidXd07bLWihwfhPqn8YeA6ZhZsYQsHUOib17lF/wVRZQCl9bacuYc7R/e6AyxuvFCsJQHVp0PEP7v+wTQ== From 17514aae82173b1d38aad8a0f4779a14b06e7855 Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 5 Apr 2021 20:37:40 +0800 Subject: [PATCH 12/14] Try to set Position to 0 in RequestPayloadBuilder. --- .../AbpRemoteStreamContentModelBinder.cs | 7 ---- .../DynamicProxying/RequestPayloadBuilder.cs | 36 +++++++++---------- .../RemoteStreamContentTestController.cs | 6 ++-- ...RemoteStreamContentTestController_Tests.cs | 8 +++-- 4 files changed, 27 insertions(+), 30 deletions(-) diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/AbpRemoteStreamContentModelBinder.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/AbpRemoteStreamContentModelBinder.cs index 8b7264fef0..da58641d7e 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/AbpRemoteStreamContentModelBinder.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/AbpRemoteStreamContentModelBinder.cs @@ -115,13 +115,6 @@ namespace Volo.Abp.AspNetCore.Mvc.ContentFormatters } } } - else - { - postedFiles.Add(new RemoteStreamContent(request.Body) - { - ContentType = request.ContentType - }); - } } } } diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/RequestPayloadBuilder.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/RequestPayloadBuilder.cs index 8532f02c7c..1096fa971e 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/RequestPayloadBuilder.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/RequestPayloadBuilder.cs @@ -53,17 +53,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying return null; } - if (value is IRemoteStreamContent remoteStreamContent) - { - var content = new StreamContent(remoteStreamContent.GetStream()); - content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(remoteStreamContent.ContentType); - content.Headers.ContentLength = remoteStreamContent.ContentLength; - return content; - } - else - { - return new StringContent(jsonSerializer.Serialize(value), Encoding.UTF8, MimeTypes.Application.Json); - } + return new StringContent(jsonSerializer.Serialize(value), Encoding.UTF8, MimeTypes.Application.Json); } private static HttpContent GenerateFormPostData(ActionApiDescriptionModel action, IReadOnlyDictionary methodArguments) @@ -80,7 +70,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying if (parameters.Any(x => x.BindingSourceId == ParameterBindingSources.FormFile)) { - var postDataBuilder = new MultipartFormDataContent(); + var formData = new MultipartFormDataContent(); foreach (var parameter in parameters) { var value = HttpActionParameterHelper.FindParameterValue(methodArguments, parameter); @@ -91,32 +81,42 @@ namespace Volo.Abp.Http.Client.DynamicProxying if (value is IRemoteStreamContent remoteStreamContent) { - var streamContent = new StreamContent(remoteStreamContent.GetStream()); + var stream = remoteStreamContent.GetStream(); + if (stream.CanSeek) + { + stream.Position = 0; + } + var streamContent = new StreamContent(stream); if (!remoteStreamContent.ContentType.IsNullOrWhiteSpace()) { streamContent.Headers.ContentType = new MediaTypeHeaderValue(remoteStreamContent.ContentType); } - postDataBuilder.Add(streamContent, parameter.Name, parameter.Name); + formData.Add(streamContent, parameter.Name, parameter.Name); } else if (value is IEnumerable remoteStreamContents) { foreach (var content in remoteStreamContents) { - var streamContent = new StreamContent(content.GetStream()); + var stream = content.GetStream(); + if (stream.CanSeek) + { + stream.Position = 0; + } + var streamContent = new StreamContent(stream); if (!content.ContentType.IsNullOrWhiteSpace()) { streamContent.Headers.ContentType = new MediaTypeHeaderValue(content.ContentType); } - postDataBuilder.Add(streamContent, parameter.Name, parameter.Name); + formData.Add(streamContent, parameter.Name, parameter.Name); } } else { - postDataBuilder.Add(new StringContent(value.ToString(), Encoding.UTF8), parameter.Name); + formData.Add(new StringContent(value.ToString(), Encoding.UTF8), parameter.Name); } } - return postDataBuilder; + return formData; } else { diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController.cs index 15491f9b21..e74c9d52e8 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController.cs @@ -25,11 +25,11 @@ namespace Volo.Abp.AspNetCore.Mvc.ContentFormatters [HttpPost] [Route("Upload")] - public async Task UploadAsync([FromBody]IRemoteStreamContent streamContent) + public async Task UploadAsync(IRemoteStreamContent file) { - using (var reader = new StreamReader(streamContent.GetStream())) + using (var reader = new StreamReader(file.GetStream())) { - return await reader.ReadToEndAsync() + ":" + streamContent.ContentType; + return await reader.ReadToEndAsync() + ":" + file.ContentType; } } } diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController_Tests.cs index 3d49a5b3ff..12745da732 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController_Tests.cs +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController_Tests.cs @@ -1,5 +1,6 @@ using System.IO; using System.Net.Http; +using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; using Shouldly; @@ -25,8 +26,11 @@ namespace Volo.Abp.AspNetCore.Mvc.ContentFormatters var memoryStream = new MemoryStream(); await memoryStream.WriteAsync(Encoding.UTF8.GetBytes("UploadAsync")); memoryStream.Position = 0; - requestMessage.Content = new StreamContent(memoryStream); - requestMessage.Content.Headers.Add("Content-Type", "application/rtf"); + + var streamContent = new StreamContent(memoryStream); + streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/rtf"); + + requestMessage.Content = new MultipartFormDataContent {{streamContent, "file", "file"}}; var response = await Client.SendAsync(requestMessage); From 297e5ad5c9312342ba130512ce25d439c9df0a2c Mon Sep 17 00:00:00 2001 From: bnymncoskuner Date: Mon, 5 Apr 2021 15:41:39 +0300 Subject: [PATCH 13/14] refactor: only warn in devMode --- .../src/lib/components/modal/modal.component.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts index d11d1bcbc2..8452a951df 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts @@ -1,3 +1,4 @@ +import { isDevMode } from '@angular/core'; import { SubscriptionService } from '@abp/ng.core'; import { Component, @@ -206,9 +207,7 @@ export class ModalComponent implements OnDestroy { setTimeout(() => { if (!this.abpClose) return; - console.warn( - 'Please use abpClose directive instead of #abpClose template variable. #abpClose will be removed in v5.0', - ); + this.warnForDeprecatedClose(); fromEvent(this.abpClose.nativeElement, 'click') .pipe(takeUntil(this.destroy$)) .subscribe(() => this.close()); @@ -216,4 +215,12 @@ export class ModalComponent implements OnDestroy { this.init.emit(); } + + private warnForDeprecatedClose() { + if (isDevMode()) { + console.warn( + 'Please use abpClose directive instead of #abpClose template variable. #abpClose will be removed in v5.0', + ); + } + } } From ca74403b31d5cca11b2846cf993913f029fff594 Mon Sep 17 00:00:00 2001 From: bnymncoskuner Date: Mon, 5 Apr 2021 15:46:16 +0300 Subject: [PATCH 14/14] refactor: move isDevMode import --- .../theme-shared/src/lib/components/modal/modal.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts index 8452a951df..4195e84d9b 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts @@ -1,4 +1,3 @@ -import { isDevMode } from '@angular/core'; import { SubscriptionService } from '@abp/ng.core'; import { Component, @@ -12,6 +11,7 @@ import { Output, TemplateRef, ViewChild, + isDevMode, } from '@angular/core'; import { NgbModal, NgbModalOptions, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; import { fromEvent, Subject } from 'rxjs';