Browse Source

Merge pull request #1573 from abpframework/feature/account-service

Feature/account service
pull/1574/head
Yasin Aydın 7 years ago
committed by GitHub
parent
commit
6af642a360
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      npm/ng-packs/packages/account/src/lib/components/login/login.component.html
  2. 20
      npm/ng-packs/packages/account/src/lib/components/register/register.component.html
  3. 33
      npm/ng-packs/packages/account/src/lib/components/register/register.component.ts
  4. 42
      npm/ng-packs/packages/account/src/lib/components/tenant-box/tenant-box.component.html
  5. 52
      npm/ng-packs/packages/account/src/lib/components/tenant-box/tenant-box.component.ts
  6. 2
      npm/ng-packs/packages/account/src/lib/models/index.ts
  7. 4
      npm/ng-packs/packages/account/src/lib/models/tenant.ts
  8. 29
      npm/ng-packs/packages/account/src/lib/models/user.ts
  9. 30
      npm/ng-packs/packages/account/src/lib/services/account.service.ts
  10. 0
      npm/ng-packs/packages/account/src/lib/services/index.ts
  11. 4
      npm/ng-packs/packages/core/src/lib/actions/session.actions.ts
  12. 1
      npm/ng-packs/packages/core/src/lib/models/session.ts
  13. 16
      npm/ng-packs/packages/core/src/lib/states/session.state.ts
  14. 3
      npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts

3
npm/ng-packs/packages/account/src/lib/components/login/login.component.html

@ -27,9 +27,6 @@
</label>
</div>
<div class="mt-2">
<button type="button" name="Action" value="Cancel" class="btn btn-secondary">
{{ 'AbpAccount::Cancel' | abpLocalization }}
</button>
<button [disabled]="inProgress" type="submit" name="Action" value="Login" class="btn btn-primary ml-1">
{{ 'AbpAccount::Login' | abpLocalization }}
</button>

20
npm/ng-packs/packages/account/src/lib/components/register/register.component.html

@ -3,22 +3,28 @@
<abp-tenant-box></abp-tenant-box>
<div class="abp-account-container">
<h2>Register</h2>
<h2>{{ 'AbpAccount::Register' | abpLocalization }}</h2>
<form [formGroup]="form" (ngSubmit)="onSubmit()" novalidate>
<div class="form-group">
<label for="input-user-name">User name</label><span> * </span
<label for="input-user-name">{{ 'AbpAccount::UserName' | abpLocalization }}</label
><span> * </span
><input autofocus type="text" id="input-user-name" class="form-control" formControlName="username" />
</div>
<div class="form-group">
<label for="input-email-address">Email address</label><span> * </span
><input type="email" id="input-email-address" class="form-control" formControlName="email" />
<label for="input-email-address">{{ 'AbpAccount::EmailAddress' | abpLocalization }}</label
><span> * </span><input type="email" id="input-email-address" class="form-control" formControlName="email" />
</div>
<div class="form-group">
<label for="input-password">Password</label><span> * </span
><input type="password" id="input-password" class="form-control" formControlName="password" />
<label for="input-password">{{ 'AbpAccount::Password' | abpLocalization }}</label
><span> * </span><input type="password" id="input-password" class="form-control" formControlName="password" />
</div>
<button type="submit" class="btn btn-primary">Register</button>
<button [disabled]="inProgress" type="submit" name="Action" value="Register" class="btn btn-primary">
{{ 'AbpAccount::Register' | abpLocalization }}
</button>
</form>
<div style="padding-top: 20px">
<a routerLink="/account/login">{{ 'AbpAccount::Login' | abpLocalization }}</a>
</div>
</div>
</div>
</div>

33
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();
}
}

42
npm/ng-packs/packages/account/src/lib/components/tenant-box/tenant-box.component.html

@ -12,33 +12,27 @@
>)
</div>
<ng-template #modalContent let-modal>
<div class="modal-header">
<h5 class="modal-title" id="modal-basic-title">
SwitchTenant
</h5>
<button type="button" class="close" aria-label="Close" (click)="modal.dismiss()">
<span aria-hidden="true">&times;</span>
</button>
</div>
<form [formGroup]="form" (ngSubmit)="save()">
<div class="modal-body">
<abp-modal *ngIf="isModalVisible" [(visible)]="isModalVisible">
<ng-template #abpHeader>
<h5>Switch Tenant</h5>
</ng-template>
<ng-template #abpBody>
<form>
<div class="mt-2">
<div class="form-group">
<label for="name">{{ 'AbpUiMultiTenancy::Name' | abpLocalization }}</label>
<input type="text" id="name" class="form-control" formControlName="name" />
<input type="text" id="name" name="tenant" class="form-control" [(ngModel)]="selected.name" />
</div>
<p>{{ 'AbpUiMultiTenancy::SwitchTenantHint' | abpLocalization }}</p>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" (click)="modal.close()">
{{ 'AbpTenantManagement::Cancel' | abpLocalization }}
</button>
<button type="submit" class="btn btn-primary">
<i class="fa fa-check mr-1"></i> <span>{{ 'AbpTenantManagement::Save' | abpLocalization }}</span>
</button>
</div>
</form>
</ng-template>
</form>
</ng-template>
<ng-template #abpFooter>
<button #abpClose type="button" class="btn btn-secondary">
{{ 'AbpTenantManagement::Cancel' | abpLocalization }}
</button>
<button type="button" class="btn btn-primary" (click)="save()">
<i class="fa fa-check mr-1"></i> <span>{{ 'AbpTenantManagement::Save' | abpLocalization }}</span>
</button>
</ng-template>
</abp-modal>

52
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<any>;
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));
});
}
}

2
npm/ng-packs/packages/account/src/lib/models/index.ts

@ -1 +1,3 @@
export * from './options';
export * from './user';
export * from './tenant';

4
npm/ng-packs/packages/account/src/lib/models/tenant.ts

@ -0,0 +1,4 @@
export interface Tenant {
success: boolean;
tenantId: string;
}

29
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;
}

30
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<Tenant> {
const request: Rest.Request<null> = {
method: 'GET',
url: `/api/abp/multi-tenancy/find-tenant/${tenantName}`,
};
return this.rest.request<null, Tenant>(request);
}
register(body: RegisterRequest): Observable<RegisterResponse> {
const request: Rest.Request<RegisterRequest> = {
method: 'POST',
url: `/api/account/register`,
body,
};
return this.rest.request<RegisterRequest, RegisterResponse>(request, { throwErr: true });
}
}

0
npm/ng-packs/packages/account/src/lib/services/index.ts

4
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) {}
}

1
npm/ng-packs/packages/core/src/lib/models/session.ts

@ -1,5 +1,6 @@
export namespace Session {
export interface State {
language: string;
tenantId: string;
}
}

16
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<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<Session.State>, { payload }: SessionSetTenantId) {
patchState({
tenantId: payload,
});
}
}

3
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);

Loading…
Cancel
Save