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..d9cf92fe8e 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 @@ -27,9 +27,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..b834d9c6c4 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::UserName' | 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..10a0e7a830 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/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/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/theme-shared/src/lib/handlers/error.handler.ts b/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts index 3291c1b1af..9d1cfb9662 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts @@ -14,6 +14,7 @@ import { Observable } from 'rxjs'; import { ErrorComponent } from '../components/errors/error.component'; import { Toaster } from '../models/toaster'; import { ConfirmationService } from '../services/confirmation.service'; +import snq from 'snq'; const DEFAULTS = { defaultError: { @@ -50,7 +51,7 @@ export class ErrorHandler { ) { actions.pipe(ofActionSuccessful(RestOccurError)).subscribe(res => { const { payload: err = {} as HttpErrorResponse | any } = res; - const body = (err as HttpErrorResponse).error.error; + const body = snq(() => (err as HttpErrorResponse).error.error, DEFAULTS.defaultError.message); if (err.headers.get('_AbpErrorFormat')) { const confirmation$ = this.showError(null, null, body);