diff --git a/npm/ng-packs/package.json b/npm/ng-packs/package.json index ec7eba7bf1..63eddb4aec 100644 --- a/npm/ng-packs/package.json +++ b/npm/ng-packs/package.json @@ -48,7 +48,7 @@ "protractor": "~5.4.0", "rxjs": "~6.4.0", "snq": "^1.0.3", - "symlink-manager": "^1.2.2", + "symlink-manager": "^1.3.0", "ts-node": "~7.0.0", "tsickle": "^0.35.0", "tslib": "^1.9.0", diff --git a/npm/ng-packs/packages/account/src/lib/components/login/login.component.html b/npm/ng-packs/packages/account/src/lib/components/login/login.component.html index da969e30a6..170db44a8e 100644 --- a/npm/ng-packs/packages/account/src/lib/components/login/login.component.html +++ b/npm/ng-packs/packages/account/src/lib/components/login/login.component.html @@ -14,6 +14,7 @@ type="text" id="login-input-user-name-or-email-address" formControlName="username" + autofocus />
@@ -27,9 +28,6 @@
- diff --git a/npm/ng-packs/packages/account/src/lib/components/register/register.component.html b/npm/ng-packs/packages/account/src/lib/components/register/register.component.html index 097af3ad0d..4590b521ac 100644 --- a/npm/ng-packs/packages/account/src/lib/components/register/register.component.html +++ b/npm/ng-packs/packages/account/src/lib/components/register/register.component.html @@ -3,22 +3,28 @@
-

Register

+

{{ 'AbpAccount::Register' | abpLocalization }}

- * + *
- * + *
- * + *
- +
+
+ {{ 'AbpAccount::Login' | abpLocalization }} +
diff --git a/npm/ng-packs/packages/account/src/lib/components/register/register.component.ts b/npm/ng-packs/packages/account/src/lib/components/register/register.component.ts index 01e6eb59bd..ee0cdf6635 100644 --- a/npm/ng-packs/packages/account/src/lib/components/register/register.component.ts +++ b/npm/ng-packs/packages/account/src/lib/components/register/register.component.ts @@ -1,8 +1,12 @@ +import { ToasterService } from '@abp/ng.theme.shared'; import { Component } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { Router } from '@angular/router'; import { validatePassword } from '@ngx-validate/core'; -import { OAuthService } from 'angular-oauth2-oidc'; +import { throwError } from 'rxjs'; +import { catchError, finalize, take } from 'rxjs/operators'; +import snq from 'snq'; +import { RegisterRequest } from '../../models'; +import { AccountService } from '../../services/account.service'; const { maxLength, minLength, required, email } = Validators; @@ -13,7 +17,9 @@ const { maxLength, minLength, required, email } = Validators; export class RegisterComponent { form: FormGroup; - constructor(private fb: FormBuilder, private oauthService: OAuthService, private router: Router) { + inProgress: boolean; + + constructor(private fb: FormBuilder, private accountService: AccountService, private toasterService: ToasterService) { this.form = this.fb.group({ username: ['', [required, maxLength(255)]], password: [ @@ -26,5 +32,26 @@ export class RegisterComponent { onSubmit() { if (this.form.invalid) return; + + this.inProgress = true; + + const newUser = { + userName: this.form.get('username').value, + password: this.form.get('password').value, + emailAddress: this.form.get('email').value, + appName: 'angular', + } as RegisterRequest; + + this.accountService + .register(newUser) + .pipe( + take(1), + catchError(err => { + this.toasterService.error(snq(() => err.error.error_description, 'An error occured.'), 'Error'); + return throwError(err); + }), + finalize(() => (this.inProgress = false)), + ) + .subscribe(); } } 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 2df7ace400..4082e1e99a 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 @@ -12,33 +12,27 @@ >) - - -
- - - -
-
+ + + + + + + diff --git a/npm/ng-packs/packages/account/src/lib/components/tenant-box/tenant-box.component.ts b/npm/ng-packs/packages/account/src/lib/components/tenant-box/tenant-box.component.ts index ab10940f10..2052d135f4 100644 --- a/npm/ng-packs/packages/account/src/lib/components/tenant-box/tenant-box.component.ts +++ b/npm/ng-packs/packages/account/src/lib/components/tenant-box/tenant-box.component.ts @@ -1,40 +1,50 @@ +import { ABP, SessionSetTenantId } from '@abp/ng.core'; +import { ToasterService } from '@abp/ng.theme.shared'; import { Component, TemplateRef, ViewChild } from '@angular/core'; -import { FormBuilder, FormGroup } from '@angular/forms'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { ABP } from '@abp/ng.core'; +import { Store } from '@ngxs/store'; +import { throwError } from 'rxjs'; +import { catchError, take } from 'rxjs/operators'; +import snq from 'snq'; +import { AccountService } from '../../services/account.service'; @Component({ selector: 'abp-tenant-box', templateUrl: './tenant-box.component.html', }) export class TenantBoxComponent { - constructor(private modalService: NgbModal, private fb: FormBuilder) {} + constructor(private store: Store, private toasterService: ToasterService, private accountService: AccountService) {} - form: FormGroup; + selected = {} as ABP.BasicItem; - selected: ABP.BasicItem; + isModalVisible: boolean; @ViewChild('modalContent', { static: false }) modalContent: TemplateRef; - createForm() { - this.form = this.fb.group({ - name: [this.selected.name], - }); - } - - openModal() { - this.createForm(); - this.modalService.open(this.modalContent); - } - onSwitch() { - this.selected = {} as ABP.BasicItem; - this.openModal(); + this.isModalVisible = true; } save() { - this.selected = this.form.value; - this.modalService.dismissAll(); + this.selected.name = this.selected.name || ''; + + this.accountService + .findTenant(this.selected.name) + .pipe( + take(1), + catchError(err => { + this.toasterService.error(snq(() => err.error.error_description, 'An error occured.'), 'Error'); + return throwError(err); + }), + ) + .subscribe(({ success, tenantId }) => { + if (success) { + this.isModalVisible = false; + } else { + this.toasterService.error(`Given tenant is not available: ${this.selected.name}`, 'Error'); + this.selected = {} as ABP.BasicItem; + } + this.store.dispatch(new SessionSetTenantId(success ? tenantId : null)); + }); } } diff --git a/npm/ng-packs/packages/account/src/lib/models/index.ts b/npm/ng-packs/packages/account/src/lib/models/index.ts index 5f30ef383a..4dcd63408e 100644 --- a/npm/ng-packs/packages/account/src/lib/models/index.ts +++ b/npm/ng-packs/packages/account/src/lib/models/index.ts @@ -1 +1,3 @@ export * from './options'; +export * from './user'; +export * from './tenant'; diff --git a/npm/ng-packs/packages/account/src/lib/models/tenant.ts b/npm/ng-packs/packages/account/src/lib/models/tenant.ts new file mode 100644 index 0000000000..08d5c321d4 --- /dev/null +++ b/npm/ng-packs/packages/account/src/lib/models/tenant.ts @@ -0,0 +1,4 @@ +export interface Tenant { + success: boolean; + tenantId: string; +} \ No newline at end of file diff --git a/npm/ng-packs/packages/account/src/lib/models/user.ts b/npm/ng-packs/packages/account/src/lib/models/user.ts new file mode 100644 index 0000000000..89e307ddc5 --- /dev/null +++ b/npm/ng-packs/packages/account/src/lib/models/user.ts @@ -0,0 +1,29 @@ +export interface RegisterRequest { + userName: string; + emailAddress: string; + password: string; + appName?: string; +} + +export interface RegisterResponse { + tenantId: string; + userName: string; + name: string; + surname: string; + email: string; + emailConfirmed: boolean; + phoneNumber: string; + phoneNumberConfirmed: boolean; + twoFactorEnabled: boolean; + lockoutEnabled: boolean; + lockoutEnd: string; + concurrencyStamp: string; + isDeleted: boolean; + deleterId: string; + deletionTime: string; + lastModificationTime: string; + lastModifierId: string; + creationTime: string; + creatorId: string; + id: string; +} diff --git a/npm/ng-packs/packages/account/src/lib/services/account.service.ts b/npm/ng-packs/packages/account/src/lib/services/account.service.ts new file mode 100644 index 0000000000..e27c32240f --- /dev/null +++ b/npm/ng-packs/packages/account/src/lib/services/account.service.ts @@ -0,0 +1,30 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { RestService, Rest } from '@abp/ng.core'; +import { RegisterResponse, RegisterRequest, Tenant } from '../models'; + +@Injectable({ + providedIn: 'root', +}) +export class AccountService { + constructor(private rest: RestService) {} + + findTenant(tenantName: string): Observable { + const request: Rest.Request = { + method: 'GET', + url: `/api/abp/multi-tenancy/find-tenant/${tenantName}`, + }; + + return this.rest.request(request); + } + + register(body: RegisterRequest): Observable { + const request: Rest.Request = { + method: 'POST', + url: `/api/account/register`, + body, + }; + + return this.rest.request(request, { throwErr: true }); + } +} diff --git a/npm/ng-packs/packages/account/src/lib/services/index.ts b/npm/ng-packs/packages/account/src/lib/services/index.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/npm/ng-packs/packages/core/src/lib/actions/session.actions.ts b/npm/ng-packs/packages/core/src/lib/actions/session.actions.ts index 7b596a25c3..278fb59f4e 100644 --- a/npm/ng-packs/packages/core/src/lib/actions/session.actions.ts +++ b/npm/ng-packs/packages/core/src/lib/actions/session.actions.ts @@ -2,3 +2,7 @@ export class SessionSetLanguage { static readonly type = '[Session] Set Language'; constructor(public payload: string) {} } +export class SessionSetTenantId { + static readonly type = '[Session] Set Tenant Id'; + constructor(public payload: string) {} +} diff --git a/npm/ng-packs/packages/core/src/lib/core.module.ts b/npm/ng-packs/packages/core/src/lib/core.module.ts index 3937da3a1e..9e822a4823 100644 --- a/npm/ng-packs/packages/core/src/lib/core.module.ts +++ b/npm/ng-packs/packages/core/src/lib/core.module.ts @@ -19,6 +19,7 @@ import { ProfileState } from './states/profile.state'; import { SessionState } from './states/session.state'; import { getInitialData } from './utils/initial-utils'; import { EllipsisDirective } from './directives/ellipsis.directive'; +import { AutofocusDirective } from './directives/autofocus.directive'; @NgModule({ imports: [ @@ -34,10 +35,11 @@ import { EllipsisDirective } from './directives/ellipsis.directive'; declarations: [ RouterOutletComponent, DynamicLayoutComponent, + AutofocusDirective, + EllipsisDirective, + LocalizationPipe, PermissionDirective, VisibilityDirective, - LocalizationPipe, - EllipsisDirective, ], exports: [ CommonModule, @@ -47,9 +49,11 @@ import { EllipsisDirective } from './directives/ellipsis.directive'; RouterModule, RouterOutletComponent, DynamicLayoutComponent, + AutofocusDirective, + EllipsisDirective, + LocalizationPipe, PermissionDirective, VisibilityDirective, - EllipsisDirective, LocalizationPipe, ], providers: [LocalizationPipe], diff --git a/npm/ng-packs/packages/core/src/lib/directives/autofocus.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/autofocus.directive.ts new file mode 100644 index 0000000000..edd7c8497a --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/directives/autofocus.directive.ts @@ -0,0 +1,15 @@ +import { Directive, ElementRef, Input, AfterViewInit } from '@angular/core'; + +@Directive({ + selector: '[autofocus]', +}) +export class AutofocusDirective implements AfterViewInit { + @Input('autofocus') + delay: number = 0; + + constructor(private elRef: ElementRef) {} + + ngAfterViewInit(): void { + setTimeout(() => this.elRef.nativeElement.focus(), this.delay); + } +} diff --git a/npm/ng-packs/packages/core/src/lib/directives/index.ts b/npm/ng-packs/packages/core/src/lib/directives/index.ts index a20dd40c55..de5846382c 100644 --- a/npm/ng-packs/packages/core/src/lib/directives/index.ts +++ b/npm/ng-packs/packages/core/src/lib/directives/index.ts @@ -1,3 +1,4 @@ +export * from './autofocus.directive'; export * from './ellipsis.directive'; export * from './permission.directive'; export * from './visibility.directive'; diff --git a/npm/ng-packs/packages/core/src/lib/models/session.ts b/npm/ng-packs/packages/core/src/lib/models/session.ts index ec595ff38d..44392b2692 100644 --- a/npm/ng-packs/packages/core/src/lib/models/session.ts +++ b/npm/ng-packs/packages/core/src/lib/models/session.ts @@ -1,5 +1,6 @@ export namespace Session { export interface State { language: string; + tenantId: string; } } diff --git a/npm/ng-packs/packages/core/src/lib/plugins/config.plugin.ts b/npm/ng-packs/packages/core/src/lib/plugins/config.plugin.ts index 719de83566..14e05c05b8 100644 --- a/npm/ng-packs/packages/core/src/lib/plugins/config.plugin.ts +++ b/npm/ng-packs/packages/core/src/lib/plugins/config.plugin.ts @@ -1,9 +1,9 @@ -import { Injectable, Inject, InjectionToken, Type } from '@angular/core'; -import { NgxsPlugin, setValue, actionMatcher, InitState, UpdateState, NgxsNextPluginFn } from '@ngxs/store'; +import { Inject, Injectable, InjectionToken } from '@angular/core'; import { Router, Routes } from '@angular/router'; -import { ABP } from '../models'; +import { actionMatcher, InitState, NgxsNextPluginFn, NgxsPlugin, setValue, UpdateState } from '@ngxs/store'; import snq from 'snq'; -import { setChildRoute, sortRoutes, organizeRoutes } from '../utils/route-utils'; +import { ABP } from '../models'; +import { organizeRoutes } from '../utils/route-utils'; export const NGXS_CONFIG_PLUGIN_OPTIONS = new InjectionToken('NGXS_CONFIG_PLUGIN_OPTIONS'); @@ -45,7 +45,7 @@ function transformRoutes(routes: Routes = [], wrappers: ABP.FullRoute[] = []): a wrappers = abpRoutes.filter(ar => ar.wrapper); const transformed = [] as ABP.FullRoute[]; routes - .filter(route => route.component || route.loadChildren) + .filter(route => (route.data || {}).routes && (route.component || route.loadChildren)) .forEach(route => { const abpPackage = abpRoutes.find(abp => abp.path.toLowerCase() === route.path.toLowerCase()); const { length } = transformed; diff --git a/npm/ng-packs/packages/core/src/lib/states/session.state.ts b/npm/ng-packs/packages/core/src/lib/states/session.state.ts index e312d605e8..8008084371 100644 --- a/npm/ng-packs/packages/core/src/lib/states/session.state.ts +++ b/npm/ng-packs/packages/core/src/lib/states/session.state.ts @@ -1,5 +1,5 @@ -import { State, Action, StateContext, Selector } from '@ngxs/store'; -import { SessionSetLanguage } from '../actions/session.actions'; +import { Action, Selector, State, StateContext } from '@ngxs/store'; +import { SessionSetLanguage, SessionSetTenantId } from '../actions/session.actions'; import { Session } from '../models/session'; @State({ @@ -12,6 +12,11 @@ export class SessionState { return language; } + @Selector() + static getSelectedTenantId({ tenantId }: Session.State): string { + return tenantId; + } + constructor() {} @Action(SessionSetLanguage) @@ -20,4 +25,11 @@ export class SessionState { language: payload, }); } + + @Action(SessionSetTenantId) + sessionSetTenantId({ patchState }: StateContext, { payload }: SessionSetTenantId) { + patchState({ + tenantId: payload, + }); + } } diff --git a/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html b/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html index 0749ef51ab..e0717ae3f5 100644 --- a/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html +++ b/npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html @@ -58,7 +58,7 @@ - +

{{ (selected?.id ? 'AbpIdentity::Edit' : 'AbpIdentity::NewRole') | abpLocalization }}

@@ -68,7 +68,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 3801acc6d2..436e5c3dd0 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 @@ -77,13 +77,13 @@
- +

{{ (selected?.id ? 'AbpIdentity::Edit' : 'AbpIdentity::NewUser') | abpLocalization }}

- +
@@ -92,7 +92,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 94b45d982b..22488241f3 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 @@ -1,4 +1,4 @@ - +

{{ 'AbpPermissionManagement::Permissions' | abpLocalization }} - {{ data.entityName }}

@@ -24,9 +24,12 @@ diff --git a/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts b/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts index 7a004003eb..ed2139ecb7 100644 --- a/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts +++ b/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts @@ -216,14 +216,14 @@ export class PermissionManagementComponent implements OnInit, OnChanges { this.permissions = getPermissions(permissionRes.groups); this.visible = true; - - setTimeout(() => { - this.setTabCheckboxState(); - this.setGrantCheckboxState(); - }, 0); }); } + initModal() { + this.setTabCheckboxState(); + this.setGrantCheckboxState(); + } + ngOnChanges({ visible }: SimpleChanges): void { if (!visible) return; 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 102b1fd506..6bf58659ef 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 @@ -88,7 +88,7 @@
- +

{{ selectedModalContent.title | abpLocalization }}

@@ -112,7 +112,7 @@
- +
@@ -123,7 +123,7 @@
- + diff --git a/npm/ng-packs/packages/theme-basic/src/lib/components/change-password/change-password.component.html b/npm/ng-packs/packages/theme-basic/src/lib/components/change-password/change-password.component.html index 76b83162b5..9993242caa 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/components/change-password/change-password.component.html +++ b/npm/ng-packs/packages/theme-basic/src/lib/components/change-password/change-password.component.html @@ -1,4 +1,4 @@ - +

{{ 'AbpIdentity::ChangePassword' | abpLocalization }}

@@ -6,7 +6,8 @@
* + > *