Browse Source

Merge pull request #5086 from abpframework/feat/volo-2927

Revised the password change logic for Angular UI
pull/5089/head
Bunyamin Coskuner 6 years ago
committed by GitHub
parent
commit
38c76d12cc
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 25
      docs/en/UI/Angular/Permission-Management.md
  2. 2
      npm/ng-packs/packages/account/src/lib/components/change-password/change-password.component.html
  3. 23
      npm/ng-packs/packages/account/src/lib/components/change-password/change-password.component.ts
  4. 10
      npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.html
  5. 29
      npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.ts
  6. 33
      npm/ng-packs/packages/account/src/lib/components/personal-settings/personal-settings.component.ts
  7. 2
      npm/ng-packs/packages/core/src/lib/models/profile.ts
  8. 2
      npm/ng-packs/packages/core/src/lib/tests/profile.service.spec.ts

25
docs/en/UI/Angular/Permission-Management.md

@ -4,36 +4,17 @@ A permission is a simple policy that is granted or prohibited for a particular u
You can get permission of authenticated user using `getGrantedPolicy` selector of `ConfigState`.
You can get permission as boolean value from store:
```js
import { Store } from '@ngxs/store';
import { ConfigState } from '@abp/ng.core';
export class YourComponent {
constructor(private store: Store) {}
ngOnInit(): void {
const canCreate = this.store.selectSnapshot(ConfigState.getGrantedPolicy('AbpIdentity.Roles.Create'));
}
// ...
}
```
Or you can get it via `ConfigStateService`:
You can get permission as boolean value:
```js
import { ConfigStateService } from '@abp/ng.core';
export class YourComponent {
constructor(private configStateService: ConfigStateService) {}
constructor(private config: ConfigStateService) {}
ngOnInit(): void {
const canCreate = this.configStateService.getGrantedPolicy('AbpIdentity.Roles.Create');
const canCreate = this.config.getGrantedPolicy('AbpIdentity.Roles.Create');
}
// ...
}
```

2
npm/ng-packs/packages/account/src/lib/components/change-password/change-password.component.html

@ -1,5 +1,5 @@
<form [formGroup]="form" (ngSubmit)="onSubmit()" [mapErrorsFn]="mapErrorsFn" validateOnSubmit>
<div class="form-group">
<div *ngIf="!hideCurrentPassword" class="form-group">
<label for="current-password">{{
'AbpIdentity::DisplayName:CurrentPassword' | abpLocalization
}}</label

23
npm/ng-packs/packages/account/src/lib/components/change-password/change-password.component.ts

@ -1,7 +1,7 @@
import { ChangePassword } from '@abp/ng.core';
import { ChangePassword, ProfileState } from '@abp/ng.core';
import { getPasswordValidators, ToasterService } from '@abp/ng.theme.shared';
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms';
import { comparePasswords, Validation } from '@ngx-validate/core';
import { Store } from '@ngxs/store';
import { finalize } from 'rxjs/operators';
@ -23,6 +23,8 @@ export class ChangePasswordComponent
inProgress: boolean;
hideCurrentPassword: boolean;
mapErrorsFn: Validation.MapErrorsFn = (errors, groupErrors, control) => {
if (PASSWORD_FIELDS.indexOf(String(control.name)) < 0) return errors;
@ -36,6 +38,8 @@ export class ChangePasswordComponent
) {}
ngOnInit(): void {
this.hideCurrentPassword = !this.store.selectSnapshot(ProfileState.getProfile).hasPassword;
const passwordValidations = getPasswordValidators(this.store);
this.form = this.fb.group(
@ -58,6 +62,8 @@ export class ChangePasswordComponent
validators: [comparePasswords(PASSWORD_FIELDS)],
},
);
if (this.hideCurrentPassword) this.form.removeControl('password');
}
onSubmit() {
@ -66,7 +72,7 @@ export class ChangePasswordComponent
this.store
.dispatch(
new ChangePassword({
currentPassword: this.form.get('password').value,
...(!this.hideCurrentPassword && { currentPassword: this.form.get('password').value }),
newPassword: this.form.get('newPassword').value,
}),
)
@ -74,17 +80,18 @@ export class ChangePasswordComponent
.subscribe({
next: () => {
this.form.reset();
this.toasterService.success('AbpAccount::PasswordChangedMessage', 'Success', {
this.toasterService.success('AbpAccount::PasswordChangedMessage', '', {
life: 5000,
});
if (this.hideCurrentPassword) {
this.hideCurrentPassword = false;
this.form.addControl('password', new FormControl('', [required]));
}
},
error: err => {
this.toasterService.error(
snq(() => err.error.error.message, 'AbpAccount::DefaultErrorMessage'),
'Error',
{
life: 7000,
},
);
},
});

10
npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.html

@ -1,11 +1,15 @@
<div id="AbpContentToolbar"></div>
<div class="card border-0 shadow-sm">
<div class="card border-0 shadow-sm min-h-400" [abpLoading]="!isProfileLoaded">
<div class="card-body">
<div class="row">
<div class="col-12 col-md-3">
<ul class="nav flex-column nav-pills" id="nav-tab" role="tablist">
<li class="nav-item" (click)="selectedTab = 0">
<li
*ngIf="!hideChangePasswordTab && isProfileLoaded"
class="nav-item"
(click)="selectedTab = 0"
>
<a
class="nav-link"
[ngClass]="{ active: selectedTab === 0 }"
@ -25,7 +29,7 @@
</li>
</ul>
</div>
<div class="col-12 col-md-9">
<div *ngIf="isProfileLoaded" class="col-12 col-md-9">
<div class="tab-content" *ngIf="selectedTab === 0" [@fadeIn]>
<div class="tab-pane active" role="tabpanel">
<h4>

29
npm/ng-packs/packages/account/src/lib/components/manage-profile/manage-profile.component.ts

@ -1,17 +1,42 @@
import { fadeIn } from '@abp/ng.theme.shared';
import { transition, trigger, useAnimation } from '@angular/animations';
import { Component } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { eAccountComponents } from '../../enums/components';
import { Store } from '@ngxs/store';
import { GetProfile, ProfileState } from '@abp/ng.core';
@Component({
selector: 'abp-manage-profile',
templateUrl: './manage-profile.component.html',
animations: [trigger('fadeIn', [transition(':enter', useAnimation(fadeIn))])],
styles: [
`
.min-h-400 {
min-height: 400px;
}
`,
],
})
export class ManageProfileComponent {
export class ManageProfileComponent implements OnInit {
selectedTab = 0;
changePasswordKey = eAccountComponents.ChangePassword;
personalSettingsKey = eAccountComponents.PersonalSettings;
isProfileLoaded: boolean;
hideChangePasswordTab: boolean;
constructor(private store: Store) {}
ngOnInit() {
this.store.dispatch(new GetProfile()).subscribe(() => {
this.isProfileLoaded = true;
if (this.store.selectSnapshot(ProfileState.getProfile).isExternal) {
this.hideChangePasswordTab = true;
this.selectedTab = 1;
}
});
}
}

33
npm/ng-packs/packages/account/src/lib/components/personal-settings/personal-settings.component.ts

@ -1,10 +1,9 @@
import { GetProfile, Profile, ProfileState, UpdateProfile } from '@abp/ng.core';
import { ProfileState, UpdateProfile } from '@abp/ng.core';
import { ToasterService } from '@abp/ng.theme.shared';
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Select, Store } from '@ngxs/store';
import { Observable } from 'rxjs';
import { take, withLatestFrom, finalize } from 'rxjs/operators';
import { ToasterService } from '@abp/ng.theme.shared';
import { Store } from '@ngxs/store';
import { finalize } from 'rxjs/operators';
import { Account } from '../../models/account';
const { maxLength, required, email } = Validators;
@ -19,9 +18,6 @@ export class PersonalSettingsComponent
OnInit,
Account.PersonalSettingsComponentInputs,
Account.PersonalSettingsComponentOutputs {
@Select(ProfileState.getProfile)
profile$: Observable<Profile.Response>;
form: FormGroup;
inProgress: boolean;
@ -37,18 +33,15 @@ export class PersonalSettingsComponent
}
buildForm() {
this.store
.dispatch(new GetProfile())
.pipe(withLatestFrom(this.profile$), take(1))
.subscribe(([, profile]) => {
this.form = this.fb.group({
userName: [profile.userName, [required, maxLength(256)]],
email: [profile.email, [required, email, maxLength(256)]],
name: [profile.name || '', [maxLength(64)]],
surname: [profile.surname || '', [maxLength(64)]],
phoneNumber: [profile.phoneNumber || '', [maxLength(16)]],
});
});
const profile = this.store.selectSnapshot(ProfileState.getProfile);
this.form = this.fb.group({
userName: [profile.userName, [required, maxLength(256)]],
email: [profile.email, [required, email, maxLength(256)]],
name: [profile.name || '', [maxLength(64)]],
surname: [profile.surname || '', [maxLength(64)]],
phoneNumber: [profile.phoneNumber || '', [maxLength(16)]],
});
}
submit() {

2
npm/ng-packs/packages/core/src/lib/models/profile.ts

@ -9,6 +9,8 @@ export namespace Profile {
name: string;
surname: string;
phoneNumber: string;
isExternal: boolean;
hasPassword: boolean;
}
export interface ChangePasswordRequest {

2
npm/ng-packs/packages/core/src/lib/tests/profile.service.spec.ts

@ -37,6 +37,8 @@ describe('ProfileService', () => {
name: 'John',
surname: 'Doe',
phoneNumber: '+123456',
isExternal: false,
hasPassword: false,
};
spectator.inject(Store).selectSnapshot.andReturn('https://abp.io');
spectator.service.update(mock).subscribe();

Loading…
Cancel
Save