Browse Source

Merge branch 'dev' of https://github.com/abpframework/abp into feature/module-template

pull/1867/head
mehmet-erim 7 years ago
parent
commit
abd610fd25
  1. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Pages/Error/Index.cshtml.cs
  2. 1
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs
  3. 1
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionFilter.cs
  4. 2
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs
  5. 3
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/AbpExceptionHandlingMiddleware.cs
  6. 2
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs
  7. 3
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/DefaultHttpExceptionStatusCodeFinder.cs
  8. 2
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/ExceptionHttpStatusCodeOptions.cs
  9. 2
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/IExceptionToErrorInfoConverter.cs
  10. 2
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/IHttpExceptionStatusCodeFinder.cs
  11. 8
      framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpClientTestModule.cs
  12. 11
      framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/PersonAppServiceClientProxy_Tests.cs
  13. 2
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/IPeopleAppService.cs
  14. 7
      framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/PeopleAppService.cs
  15. 2
      modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml
  16. 2
      modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs
  17. 3
      npm/ng-packs/packages/core/src/lib/core.module.ts
  18. 12
      npm/ng-packs/packages/core/src/lib/directives/sort.directive.ts
  19. 2
      npm/ng-packs/packages/core/src/lib/pipes/sort.pipe.ts
  20. 1
      npm/ng-packs/packages/core/src/public-api.ts
  21. 8
      npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html
  22. 36
      npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.ts
  23. 28
      npm/ng-packs/packages/identity/src/lib/components/users/users.component.html
  24. 36
      npm/ng-packs/packages/identity/src/lib/components/users/users.component.ts
  25. 13
      npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html
  26. 34
      npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.ts
  27. 1
      npm/ng-packs/packages/theme-shared/src/lib/components/index.ts
  28. 3
      npm/ng-packs/packages/theme-shared/src/lib/components/sort-order-icon/sort-order-icon.component.html
  29. 61
      npm/ng-packs/packages/theme-shared/src/lib/components/sort-order-icon/sort-order-icon.component.ts
  30. 3
      npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/Pages/Error/Index.cshtml.cs

@ -2,7 +2,7 @@ using System;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Volo.Abp.AspNetCore.Mvc.ExceptionHandling;
using Volo.Abp.AspNetCore.ExceptionHandling;
using Volo.Abp.Http;
namespace Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Pages.Error

1
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs

@ -111,6 +111,7 @@ namespace Volo.Abp.AspNetCore.Mvc
var application = context.Services.GetSingletonInstance<IAbpApplication>();
partManager.FeatureProviders.Add(new AbpConventionalControllerFeatureProvider(application));
partManager.ApplicationParts.Add(new AssemblyPart(typeof(AbpAspNetCoreMvcModule).Assembly));
Configure<MvcOptions>(mvcOptions =>
{

1
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/AbpExceptionFilter.cs

@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.AspNetCore.ExceptionHandling;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http;
using Volo.Abp.Json;

2
framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs

@ -4,7 +4,7 @@ using Microsoft.AspNetCore.RequestLocalization;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp;
using Volo.Abp.AspNetCore.Auditing;
using Volo.Abp.AspNetCore.Mvc.ExceptionHandling;
using Volo.Abp.AspNetCore.ExceptionHandling;
using Volo.Abp.AspNetCore.Tracing;
using Volo.Abp.AspNetCore.Uow;
using Volo.Abp.DependencyInjection;

3
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/AbpExceptionHandlingMiddleware.cs

@ -4,12 +4,13 @@ using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Uow;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http;
using Volo.Abp.Json;
namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling
namespace Volo.Abp.AspNetCore.ExceptionHandling
{
public class AbpExceptionHandlingMiddleware : IMiddleware, ITransientDependency
{

2
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/DefaultExceptionToErrorInfoConverter.cs

@ -15,7 +15,7 @@ using Volo.Abp.Localization;
using Volo.Abp.Localization.ExceptionHandling;
using Volo.Abp.Validation;
namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling
namespace Volo.Abp.AspNetCore.ExceptionHandling
{
public class DefaultExceptionToErrorInfoConverter : IExceptionToErrorInfoConverter, ITransientDependency
{

3
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/DefaultHttpExceptionStatusCodeFinder.cs

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Net;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
@ -9,7 +8,7 @@ using Volo.Abp.Domain.Entities;
using Volo.Abp.ExceptionHandling;
using Volo.Abp.Validation;
namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling
namespace Volo.Abp.AspNetCore.ExceptionHandling
{
public class DefaultHttpExceptionStatusCodeFinder : IHttpExceptionStatusCodeFinder, ITransientDependency
{

2
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/ExceptionHttpStatusCodeOptions.cs

@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.Net;
namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling
namespace Volo.Abp.AspNetCore.ExceptionHandling
{
public class ExceptionHttpStatusCodeOptions
{

2
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/IExceptionToErrorInfoConverter.cs

@ -1,7 +1,7 @@
using System;
using Volo.Abp.Http;
namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling
namespace Volo.Abp.AspNetCore.ExceptionHandling
{
/// <summary>
/// This interface can be implemented to convert an <see cref="Exception"/> object to an <see cref="RemoteServiceErrorInfo"/> object.

2
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/IHttpExceptionStatusCodeFinder.cs

@ -2,7 +2,7 @@
using System.Net;
using Microsoft.AspNetCore.Http;
namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling
namespace Volo.Abp.AspNetCore.ExceptionHandling
{
public interface IHttpExceptionStatusCodeFinder
{

8
framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/AbpHttpClientTestModule.cs

@ -1,5 +1,4 @@
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Http.Client;
using Volo.Abp.Http.DynamicProxying;
@ -23,11 +22,6 @@ namespace Volo.Abp.Http
{
options.RemoteServices.Default = new RemoteServiceConfiguration("/");
});
//This is needed after ASP.NET Core 3.0 upgrade.
context.Services.AddMvc()
.PartManager.ApplicationParts
.Add(new AssemblyPart(typeof(AbpAspNetCoreMvcModule).Assembly));
}
}
}

11
framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/PersonAppServiceClientProxy_Tests.cs

@ -5,7 +5,7 @@ using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Http.Modeling;
using Volo.Abp.Http.Client;
using Volo.Abp.TestApp.Application;
using Volo.Abp.TestApp.Application.Dto;
using Volo.Abp.TestApp.Domain;
@ -103,6 +103,15 @@ namespace Volo.Abp.Http.DynamicProxying
personInDb.Age.ShouldBe(person.Age);
}
[Fact]
public async Task GetWithAuthorized()
{
(await Assert.ThrowsAsync<AbpRemoteCallException>(async () =>
{
await _peopleAppService.GetWithAuthorized();
})).Error.Message.ShouldContain("Authorization");
}
[Fact]
public async Task GetWithComplexType()
{

2
framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/IPeopleAppService.cs

@ -14,6 +14,8 @@ namespace Volo.Abp.TestApp.Application
Task RemovePhone(Guid id, string number);
Task GetWithAuthorized();
Task<GetWithComplexTypeInput> GetWithComplexType(GetWithComplexTypeInput input);
}
}

7
framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/PeopleAppService.cs

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Application.Dtos;
using Volo.Abp.TestApp.Domain;
using Volo.Abp.Domain.Repositories;
@ -46,6 +47,12 @@ namespace Volo.Abp.TestApp.Application
Repository.Update(person);
}
[Authorize]
public virtual Task GetWithAuthorized()
{
return Task.CompletedTask;
}
public Task<GetWithComplexTypeInput> GetWithComplexType(GetWithComplexTypeInput input)
{
return Task.FromResult(input);

2
modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml

@ -87,7 +87,7 @@
</label>
</div>
<select asp-items="Model.ProjectSelectItems" class="form-control" onchange="window.location.replace(this.value)"></select>
<select asp-items="Model.ProjectSelectItems" class="form-control" onchange="window.location.pathname = this.value"></select>
</div>
</div>
</div>

2
modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs

@ -187,7 +187,7 @@ namespace Volo.Docs.Pages.Documents.Project
ProjectSelectItems = projects.Items.Select(p => new SelectListItem
{
Text = p.Name,
Value = p.Id != Project.Id ? "/" + DocumentsUrlPrefix + LanguageCode + "/" + p.ShortName + "/" + DocsAppConsts.Latest : null,
Value = p.Id != Project.Id ? DocumentsUrlPrefix + LanguageCode + "/" + p.ShortName + "/" + DocsAppConsts.Latest : null,
Selected = p.Id == Project.Id
}).ToList();
}

3
npm/ng-packs/packages/core/src/lib/core.module.ts

@ -27,6 +27,7 @@ import { getInitialData, localeInitializer } from './utils/initial-utils';
import { ConfigPlugin, NGXS_CONFIG_PLUGIN_OPTIONS } from './plugins/config/config.plugin';
import { ForDirective } from './directives/for.directive';
import { AbstractNgModelComponent } from './abstracts/ng-model.component';
import { SortDirective } from './directives/sort.directive';
@NgModule({
imports: [
@ -46,6 +47,7 @@ import { AbstractNgModelComponent } from './abstracts/ng-model.component';
EllipsisDirective,
ForDirective,
FormSubmitDirective,
SortDirective,
LocalizationPipe,
SortPipe,
PermissionDirective,
@ -68,6 +70,7 @@ import { AbstractNgModelComponent } from './abstracts/ng-model.component';
FormSubmitDirective,
LocalizationPipe,
SortPipe,
SortDirective,
PermissionDirective,
VisibilityDirective,
InputEventDebounceDirective,

12
npm/ng-packs/packages/core/src/lib/directives/sort.directive.ts

@ -0,0 +1,12 @@
import { Directive, ElementRef, Input, Optional, Self } from '@angular/core';
import { Table } from 'primeng/table';
@Directive({
selector: '[abpSort]',
})
export class SortDirective {
constructor(private elementRef: ElementRef, @Optional() @Self() table: Table) {
console.warn(elementRef);
setInterval(() => console.warn(table.value), 1000);
}
}

2
npm/ng-packs/packages/core/src/lib/pipes/sort.pipe.ts

@ -9,7 +9,7 @@ export type SortOrder = 'asc' | 'desc';
export class SortPipe implements PipeTransform {
intialValue: any[];
transform(value: any[], sortOrder: SortOrder = 'asc', sortKey: string): any {
transform(value: any[], sortOrder: SortOrder | string = 'asc', sortKey?: string): any {
sortOrder = sortOrder && (sortOrder.toLowerCase() as any);
if (!this.intialValue) this.intialValue = clone(value);

1
npm/ng-packs/packages/core/src/public-api.ts

@ -12,6 +12,7 @@ export * from './lib/enums';
export * from './lib/guards';
export * from './lib/interceptors';
export * from './lib/models';
export * from './lib/pipes';
export * from './lib/plugins';
export * from './lib/services';
export * from './lib/states';

8
npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html

@ -24,7 +24,7 @@
</div>
<p-table
*ngIf="[130, 200] as columnWidths"
[value]="data$ | async"
[value]="data$ | async | abpSort: sortOrder:sortKey"
[lazy]="true"
[lazyLoadOnInit]="false"
[paginator]="true"
@ -51,11 +51,9 @@
<ng-template pTemplate="header" let-columns>
<tr>
<th>{{ 'AbpIdentity::Actions' | abpLocalization }}</th>
<th pResizableColumn (click)="changeSortOrder()">
<th pResizableColumn (click)="sortByKey('name')">
{{ 'AbpIdentity::RoleName' | abpLocalization }}
<span class="float-right"
><i [ngClass]="['fa', sortOrder === 'desc' ? 'fa-sort-desc' : 'fa-sort-asc']"></i
></span>
<abp-sort-order-icon key="name" [selectedKey]="sortKey" [order]="sortOrder"></abp-sort-order-icon>
</th>
</tr>
</ng-template>

36
npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.ts

@ -11,7 +11,7 @@ import { IdentityState } from '../../states/identity.state';
@Component({
selector: 'abp-roles',
templateUrl: './roles.component.html'
templateUrl: './roles.component.html',
})
export class RolesComponent {
@Select(IdentityState.getRoles)
@ -30,15 +30,15 @@ export class RolesComponent {
providerKey: string;
pageQuery: ABP.PageQueryParams = {
sorting: 'name'
};
pageQuery: ABP.PageQueryParams = {};
loading = false;
modalBusy = false;
sortOrder = 'asc';
sortOrder: string = '';
sortKey: string = '';
@ViewChild('modalContent', { static: false })
modalContent: TemplateRef<any>;
@ -54,10 +54,10 @@ export class RolesComponent {
this.form = this.fb.group({
name: new FormControl({ value: this.selected.name || '', disabled: this.selected.isStatic }, [
Validators.required,
Validators.maxLength(256)
Validators.maxLength(256),
]),
isDefault: [this.selected.isDefault || false],
isPublic: [this.selected.isPublic || false]
isPublic: [this.selected.isPublic || false],
});
}
@ -89,7 +89,7 @@ export class RolesComponent {
.dispatch(
this.selected.id
? new UpdateRole({ ...this.form.value, id: this.selected.id })
: new CreateRole(this.form.value)
: new CreateRole(this.form.value),
)
.subscribe(() => {
this.modalBusy = false;
@ -100,7 +100,7 @@ export class RolesComponent {
delete(id: string, name: string) {
this.confirmationService
.warn('AbpIdentity::RoleDeletionConfirmationMessage', 'AbpIdentity::AreYouSure', {
messageLocalizationParams: [name]
messageLocalizationParams: [name],
})
.subscribe((status: Toaster.Status) => {
if (status === Toaster.Status.confirm) {
@ -124,7 +124,21 @@ export class RolesComponent {
.subscribe();
}
changeSortOrder() {
this.sortOrder = this.sortOrder.toLowerCase() === 'asc' ? 'desc' : 'asc';
sortByKey(sortKey: string) {
this.sortKey = sortKey;
switch (this.sortOrder) {
case '':
this.sortOrder = 'asc';
break;
case 'asc':
this.sortOrder = 'desc';
break;
case 'desc':
this.sortOrder = '';
this.sortKey = '';
break;
default:
break;
}
}
}

28
npm/ng-packs/packages/identity/src/lib/components/users/users.component.html

@ -29,8 +29,9 @@
/></label>
</div>
<p-table
abpSort
*ngIf="[130, 200, 200, 200] as columnWidths"
[value]="data$ | async"
[value]="data$ | async | abpSort: sortOrder:sortKey"
[lazy]="true"
[lazyLoadOnInit]="false"
[paginator]="true"
@ -57,14 +58,27 @@
<ng-template pTemplate="header">
<tr>
<th>{{ 'AbpIdentity::Actions' | abpLocalization }}</th>
<th pResizableColumn (click)="changeSortOrder()">
<th pResizableColumn (click)="usernameSortIcon.sort('userName')">
{{ 'AbpIdentity::UserName' | abpLocalization }}
<span class="float-right"
><i [ngClass]="['fa', sortOrder === 'desc' ? 'fa-sort-desc' : 'fa-sort-asc']"></i
></span>
<abp-sort-order-icon
#usernameSortIcon
key="userName"
[(selectedKey)]="sortKey"
[(order)]="sortOrder"
></abp-sort-order-icon>
</th>
<th pResizableColumn (click)="usernameSortIcon.sort('email')">
{{ 'AbpIdentity::EmailAddress' | abpLocalization }}
<abp-sort-order-icon key="email" [(selectedKey)]="sortKey" [(order)]="sortOrder"></abp-sort-order-icon>
</th>
<th pResizableColumn (click)="usernameSortIcon.sort('phoneNumber')">
{{ 'AbpIdentity::PhoneNumber' | abpLocalization }}
<abp-sort-order-icon
key="phoneNumber"
[(selectedKey)]="sortKey"
[(order)]="sortOrder"
></abp-sort-order-icon>
</th>
<th pResizableColumn>{{ 'AbpIdentity::EmailAddress' | abpLocalization }}</th>
<th pResizableColumn>{{ 'AbpIdentity::PhoneNumber' | abpLocalization }}</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-data>

36
npm/ng-packs/packages/identity/src/lib/components/users/users.component.ts

@ -12,13 +12,13 @@ import {
GetUserById,
GetUserRoles,
GetUsers,
UpdateUser
UpdateUser,
} from '../../actions/identity.actions';
import { Identity } from '../../models/identity';
import { IdentityState } from '../../states/identity.state';
@Component({
selector: 'abp-users',
templateUrl: './users.component.html'
templateUrl: './users.component.html',
})
export class UsersComponent {
@Select(IdentityState.getUsers)
@ -42,9 +42,7 @@ export class UsersComponent {
providerKey: string;
pageQuery: ABP.PageQueryParams = {
sorting: 'userName'
};
pageQuery: ABP.PageQueryParams = {};
isModalVisible: boolean;
@ -52,7 +50,9 @@ export class UsersComponent {
modalBusy = false;
sortOrder = 'asc';
sortOrder = '';
sortKey = '';
trackByFn: TrackByFunction<AbstractControl> = (index, item) => Object.keys(item)[0] || index;
@ -80,10 +80,10 @@ export class UsersComponent {
roleNames: this.fb.array(
this.roles.map(role =>
this.fb.group({
[role.name]: [!!snq(() => this.selectedUserRoles.find(userRole => userRole.id === role.id))]
})
)
)
[role.name]: [!!snq(() => this.selectedUserRoles.find(userRole => userRole.id === role.id))],
}),
),
),
});
if (!this.selected.userName) {
this.form.addControl('password', new FormControl('', [Validators.required, Validators.maxLength(32)]));
@ -107,7 +107,7 @@ export class UsersComponent {
.pipe(
switchMap(() => this.store.dispatch(new GetUserRoles(id))),
pluck('IdentityState'),
take(1)
take(1),
)
.subscribe((state: Identity.State) => {
this.selected = state.selectedUser;
@ -123,7 +123,7 @@ export class UsersComponent {
const { roleNames } = this.form.value;
const mappedRoleNames = snq(
() => roleNames.filter(role => !!role[Object.keys(role)[0]]).map(role => Object.keys(role)[0]),
[]
[],
);
this.store
@ -132,12 +132,12 @@ export class UsersComponent {
? new UpdateUser({
...this.form.value,
id: this.selected.id,
roleNames: mappedRoleNames
roleNames: mappedRoleNames,
})
: new CreateUser({
...this.form.value,
roleNames: mappedRoleNames
})
roleNames: mappedRoleNames,
}),
)
.subscribe(() => {
this.modalBusy = false;
@ -148,7 +148,7 @@ export class UsersComponent {
delete(id: string, userName: string) {
this.confirmationService
.warn('AbpIdentity::UserDeletionConfirmationMessage', 'AbpIdentity::AreYouSure', {
messageLocalizationParams: [userName]
messageLocalizationParams: [userName],
})
.subscribe((status: Toaster.Status) => {
if (status === Toaster.Status.confirm) {
@ -171,8 +171,4 @@ export class UsersComponent {
.pipe(finalize(() => (this.loading = false)))
.subscribe();
}
changeSortOrder() {
this.sortOrder = this.sortOrder.toLowerCase() === 'asc' ? 'desc' : 'asc';
}
}

13
npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.html

@ -31,7 +31,7 @@
</div>
<p-table
*ngIf="[130, 200] as columnWidths"
[value]="data$ | async | abpSort: sortOrder"
[value]="data$ | async | abpSort: sortOrder:sortKey"
[lazy]="true"
[lazyLoadOnInit]="false"
[paginator]="true"
@ -58,11 +58,14 @@
<ng-template pTemplate="header" let-columns>
<tr>
<th>{{ 'AbpTenantManagement::Actions' | abpLocalization }}</th>
<th pResizableColumn (click)="changeSortOrder()">
<th pResizableColumn (click)="sortOrderIcon.sort('name')">
{{ 'AbpTenantManagement::TenantName' | abpLocalization }}
<span class="float-right"
><i [ngClass]="['fa', sortOrder === 'desc' ? 'fa-sort-desc' : 'fa-sort-asc']"></i
></span>
<abp-sort-order-icon
#sortOrderIcon
key="name"
[(selectedKey)]="sortKey"
[(order)]="sortOrder"
></abp-sort-order-icon>
</th>
</tr>
</ng-template>

34
npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.ts

@ -10,7 +10,7 @@ import {
DeleteTenant,
GetTenants,
GetTenantById,
UpdateTenant
UpdateTenant,
} from '../../actions/tenant-management.actions';
import { TenantManagementService } from '../../services/tenant-management.service';
import { TenantManagementState } from '../../states/tenant-management.state';
@ -23,7 +23,7 @@ interface SelectedModalContent {
@Component({
selector: 'abp-tenants',
templateUrl: './tenants.component.html'
templateUrl: './tenants.component.html',
})
export class TenantsComponent {
@Select(TenantManagementState.get)
@ -50,15 +50,15 @@ export class TenantsComponent {
_useSharedDatabase: boolean;
pageQuery: ABP.PageQueryParams = {
sorting: 'name'
};
pageQuery: ABP.PageQueryParams = {};
loading = false;
modalBusy = false;
sortOrder = 'asc';
sortOrder = '';
sortKey = '';
get useSharedDatabase(): boolean {
return this.defaultConnectionStringForm.get('useSharedDatabase').value;
@ -78,7 +78,7 @@ export class TenantsComponent {
private confirmationService: ConfirmationService,
private tenantService: TenantManagementService,
private fb: FormBuilder,
private store: Store
private store: Store,
) {}
onSearch(value) {
@ -88,14 +88,14 @@ export class TenantsComponent {
private createTenantForm() {
this.tenantForm = this.fb.group({
name: [this.selected.name || '', [Validators.required, Validators.maxLength(256)]]
name: [this.selected.name || '', [Validators.required, Validators.maxLength(256)]],
});
}
private createDefaultConnectionStringForm() {
this.defaultConnectionStringForm = this.fb.group({
useSharedDatabase: this._useSharedDatabase,
defaultConnectionString: [this.defaultConnectionString || '']
defaultConnectionString: [this.defaultConnectionString || ''],
});
}
@ -103,7 +103,7 @@ export class TenantsComponent {
this.selectedModalContent = {
title,
template,
type
type,
};
this.isModalVisible = true;
@ -117,7 +117,7 @@ export class TenantsComponent {
switchMap(selected => {
this.selected = selected;
return this.tenantService.getDefaultConnectionString(id);
})
}),
)
.subscribe(fetchedConnectionString => {
this._useSharedDatabase = fetchedConnectionString ? false : true;
@ -158,7 +158,7 @@ export class TenantsComponent {
.deleteDefaultConnectionString(this.selected.id)
.pipe(
take(1),
finalize(() => (this.modalBusy = false))
finalize(() => (this.modalBusy = false)),
)
.subscribe(() => {
this.isModalVisible = false;
@ -168,7 +168,7 @@ export class TenantsComponent {
.updateDefaultConnectionString({ id: this.selected.id, defaultConnectionString: this.connectionString })
.pipe(
take(1),
finalize(() => (this.modalBusy = false))
finalize(() => (this.modalBusy = false)),
)
.subscribe(() => {
this.isModalVisible = false;
@ -184,7 +184,7 @@ export class TenantsComponent {
.dispatch(
this.selected.id
? new UpdateTenant({ ...this.tenantForm.value, id: this.selected.id })
: new CreateTenant(this.tenantForm.value)
: new CreateTenant(this.tenantForm.value),
)
.pipe(finalize(() => (this.modalBusy = false)))
.subscribe(() => {
@ -195,7 +195,7 @@ export class TenantsComponent {
delete(id: string, name: string) {
this.confirmationService
.warn('AbpTenantManagement::TenantDeletionConfirmationMessage', 'AbpTenantManagement::AreYouSure', {
messageLocalizationParams: [name]
messageLocalizationParams: [name],
})
.subscribe((status: Toaster.Status) => {
if (status === Toaster.Status.confirm) {
@ -218,8 +218,4 @@ export class TenantsComponent {
.pipe(finalize(() => (this.loading = false)))
.subscribe();
}
changeSortOrder() {
this.sortOrder = this.sortOrder.toLowerCase() === 'asc' ? 'desc' : 'asc';
}
}

1
npm/ng-packs/packages/theme-shared/src/lib/components/index.ts

@ -8,3 +8,4 @@ export * from './modal/modal.component';
export * from './profile/profile.component';
export * from './table-empty-message/table-empty-message.component';
export * from './toast/toast.component';
export * from './sort-order-icon/sort-order-icon.component';

3
npm/ng-packs/packages/theme-shared/src/lib/components/sort-order-icon/sort-order-icon.component.html

@ -0,0 +1,3 @@
<span class="float-right {{ iconClass }}">
<i class="fa {{ icon }}"></i>
</span>

61
npm/ng-packs/packages/theme-shared/src/lib/components/sort-order-icon/sort-order-icon.component.ts

@ -0,0 +1,61 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'abp-sort-order-icon',
templateUrl: './sort-order-icon.component.html',
})
export class SortOrderIconComponent {
private _order: string;
private _selectedKey: string;
@Input()
set selectedKey(value: string) {
this._selectedKey = value;
this.selectedKeyChange.emit(value);
}
get selectedKey(): string {
return this._selectedKey;
}
@Output() readonly selectedKeyChange = new EventEmitter<string>();
@Input()
key: string;
@Input()
set order(value: string) {
this._order = value;
this.orderChange.emit(value);
}
get order(): string {
return this._order;
}
@Output() readonly orderChange = new EventEmitter<string>();
@Input()
iconClass: string;
get icon(): string {
if (!this.selectedKey) return 'fa-sort';
if (this.selectedKey === this.key) return `fa-sort-${this.order}`;
else return '';
}
sort(key: string) {
this.selectedKey = key;
switch (this.order) {
case '':
this.order = 'asc';
break;
case 'asc':
this.order = 'desc';
this.orderChange.emit('desc');
break;
case 'desc':
this.order = '';
this.selectedKey = '';
break;
}
}
}

3
npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts

@ -14,6 +14,7 @@ import { LoaderBarComponent } from './components/loader-bar/loader-bar.component
import { ModalComponent } from './components/modal/modal.component';
import { ProfileComponent } from './components/profile/profile.component';
import { ToastComponent } from './components/toast/toast.component';
import { SortOrderIconComponent } from './components/sort-order-icon/sort-order-icon.component';
import styles from './contants/styles';
import { ErrorHandler } from './handlers/error.handler';
import { chartJsLoaded$ } from './utils/widget-utils';
@ -54,6 +55,7 @@ export function appendScript(injector: Injector) {
ProfileComponent,
TableEmptyMessageComponent,
ToastComponent,
SortOrderIconComponent,
],
exports: [
BreadcrumbComponent,
@ -66,6 +68,7 @@ export function appendScript(injector: Injector) {
ProfileComponent,
TableEmptyMessageComponent,
ToastComponent,
SortOrderIconComponent,
],
entryComponents: [ErrorComponent],
})

Loading…
Cancel
Save