Browse Source

feature(identity): change add/edit modal

pull/1556/head
TheDiaval 7 years ago
parent
commit
1ca585f1ac
  1. 40
      npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.html
  2. 16
      npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.ts
  3. 205
      npm/ng-packs/packages/identity/src/lib/components/users/users.component.html
  4. 151
      npm/ng-packs/packages/identity/src/lib/components/users/users.component.ts
  5. 2
      npm/ng-packs/packages/identity/src/lib/identity.module.ts

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

@ -58,17 +58,13 @@
</div>
</div>
<ng-template #modalContent let-modal>
<div class="modal-header">
<h5 class="modal-title" id="modal-basic-title">
{{ (selected?.id ? 'AbpIdentity::Edit' : 'AbpIdentity::NewRole') | abpLocalization }}
</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 size="md" [(visible)]="isModalVisible" *ngIf="isModalVisible" [centered]="true">
<ng-template #abpHeader>
<h3>{{ (selected?.id ? 'AbpIdentity::Edit' : 'AbpIdentity::NewRole') | abpLocalization }}</h3>
</ng-template>
<ng-template #abpBody>
<form [formGroup]="form">
<div class="form-group">
<label for="role-name">{{ 'AbpIdentity::RoleName' | abpLocalization }}</label
><span> * </span>
@ -88,18 +84,18 @@
'AbpIdentity::DisplayName:IsPublic' | abpLocalization
}}</label>
</div>
</div>
</form>
</ng-template>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" (click)="modal.close()">
{{ 'AbpIdentity::Cancel' | abpLocalization }}
</button>
<button type="submit" class="btn btn-primary">
<i class="fa fa-check mr-1"></i> <span>{{ 'AbpIdentity::Save' | abpLocalization }}</span>
</button>
</div>
</form>
</ng-template>
<ng-template #abpFooter>
<button type="button" class="btn btn-secondary" #abpClose>
{{ 'AbpIdentity::Cancel' | abpLocalization }}
</button>
<button type="button" class="btn btn-primary" (click)="save()">
<i class="fa fa-check mr-1"></i> <span>{{ 'AbpIdentity::Save' | abpLocalization }}</span>
</button>
</ng-template>
</abp-modal>
<abp-permission-management
[(visible)]="visiblePermissions"

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

@ -1,7 +1,6 @@
import { Component, TemplateRef, ViewChild } from '@angular/core';
import { Select, Store } from '@ngxs/store';
import { Observable } from 'rxjs';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { IdentityState } from '../../states/identity.state';
import { Identity } from '../../models/identity';
@ -26,6 +25,8 @@ export class RolesComponent {
selected: Identity.RoleItem;
isModalVisible: boolean;
visiblePermissions: boolean = false;
providerKey: string;
@ -33,12 +34,7 @@ export class RolesComponent {
@ViewChild('modalContent', { static: false })
modalContent: TemplateRef<any>;
constructor(
private confirmationService: ConfirmationService,
private modalService: NgbModal,
private fb: FormBuilder,
private store: Store,
) {}
constructor(private confirmationService: ConfirmationService, private fb: FormBuilder, private store: Store) {}
createForm() {
this.form = this.fb.group({
@ -50,7 +46,7 @@ export class RolesComponent {
openModal() {
this.createForm();
this.modalService.open(this.modalContent);
this.isModalVisible = true;
}
onAdd() {
@ -77,7 +73,9 @@ export class RolesComponent {
? new IdentityUpdateRole({ ...this.form.value, id: this.selected.id })
: new IdentityAddRole(this.form.value),
)
.subscribe(() => this.modalService.dismissAll());
.subscribe(() => {
this.isModalVisible = false;
});
}
delete(id: string, name: string) {

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

@ -77,119 +77,118 @@
</div>
</div>
<ng-template #modalContent let-modal>
<div class="modal-header">
<h5 class="modal-title" id="modal-basic-title">
{{ (selected?.id ? 'AbpIdentity::Edit' : 'AbpIdentity::NewUser') | abpLocalization }}
</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">
<ngb-tabset>
<ngb-tab [title]="'AbpIdentity::UserInformations' | abpLocalization">
<ng-template ngbTabContent>
<div class="mt-2">
<div class="form-group">
<label for="user-name">{{ 'AbpIdentity::UserName' | abpLocalization }}</label
><span> * </span>
<input type="text" id="user-name" class="form-control" formControlName="userName" />
</div>
<abp-modal [(visible)]="isModalVisible" *ngIf="isModalVisible" [centered]="true">
<ng-template #abpHeader>
<h3>{{ (selected?.id ? 'AbpIdentity::Edit' : 'AbpIdentity::NewUser') | abpLocalization }}</h3>
</ng-template>
<div class="form-group">
<label for="name">{{ 'AbpIdentity::Name' | abpLocalization }}</label>
<input type="text" id="name" class="form-control" formControlName="name" />
</div>
<ng-template #abpBody>
<perfect-scrollbar class="ps-show-always" style="max-height: 65vh;">
<form [formGroup]="form">
<ngb-tabset>
<ngb-tab [title]="'AbpIdentity::UserInformations' | abpLocalization">
<ng-template ngbTabContent>
<div class="mt-2">
<div class="form-group">
<label for="user-name">{{ 'AbpIdentity::UserName' | abpLocalization }}</label
><span> * </span>
<input type="text" id="user-name" class="form-control" formControlName="userName" />
</div>
<div class="form-group">
<label for="surname">{{ 'AbpIdentity::DisplayName:Surname' | abpLocalization }}</label>
<input type="text" id="surname" class="form-control" formControlName="surname" />
</div>
<div class="form-group">
<label for="name">{{ 'AbpIdentity::DisplayName:Name' | abpLocalization }}</label>
<input type="text" id="name" class="form-control" formControlName="name" />
</div>
<div class="form-group">
<label for="password">{{ 'AbpIdentity::Password' | abpLocalization }}</label
><span> * </span>
<input
type="password"
id="password"
autocomplete="new-password"
class="form-control"
formControlName="password"
/>
</div>
<div class="form-group">
<label for="surname">{{ 'AbpIdentity::DisplayName:Surname' | abpLocalization }}</label>
<input type="text" id="surname" class="form-control" formControlName="surname" />
</div>
<div class="form-group">
<label for="email">{{ 'AbpIdentity::EmailAddress' | abpLocalization }}</label
><span> * </span>
<input type="text" id="email" class="form-control" formControlName="email" />
</div>
<div class="form-group">
<label for="password">{{ 'AbpIdentity::Password' | abpLocalization }}</label
><span> * </span>
<input
type="password"
id="password"
autocomplete="new-password"
class="form-control"
formControlName="password"
/>
</div>
<div class="form-group">
<label for="phone-number">{{ 'AbpIdentity::PhoneNumber' | abpLocalization }}</label>
<input type="text" id="phone-number" class="form-control" formControlName="phoneNumber" />
</div>
<div class="form-group">
<label for="email">{{ 'AbpIdentity::EmailAddress' | abpLocalization }}</label
><span> * </span>
<input type="text" id="email" class="form-control" formControlName="email" />
</div>
<div class="custom-checkbox custom-control mb-2">
<input
type="checkbox"
id="lockout-checkbox"
class="custom-control-input"
formControlName="lockoutEnabled"
/>
<label class="custom-control-label" for="lockout-checkbox">{{
'AbpIdentity::DisplayName:LockoutEnabled' | abpLocalization
}}</label>
</div>
<div class="form-group">
<label for="phone-number">{{ 'AbpIdentity::PhoneNumber' | abpLocalization }}</label>
<input type="text" id="phone-number" class="form-control" formControlName="phoneNumber" />
</div>
<div class="custom-checkbox custom-control mb-2">
<input
type="checkbox"
id="two-factor-checkbox"
class="custom-control-input"
formControlName="twoFactorEnabled"
/>
<label class="custom-control-label" for="two-factor-checkbox">{{
'AbpIdentity::DisplayName:TwoFactorEnabled' | abpLocalization
}}</label>
<div class="custom-checkbox custom-control mb-2">
<input
type="checkbox"
id="lockout-checkbox"
class="custom-control-input"
formControlName="lockoutEnabled"
/>
<label class="custom-control-label" for="lockout-checkbox">{{
'AbpIdentity::DisplayName:LockoutEnabled' | abpLocalization
}}</label>
</div>
<div class="custom-checkbox custom-control mb-2">
<input
type="checkbox"
id="two-factor-checkbox"
class="custom-control-input"
formControlName="twoFactorEnabled"
/>
<label class="custom-control-label" for="two-factor-checkbox">{{
'AbpIdentity::DisplayName:TwoFactorEnabled' | abpLocalization
}}</label>
</div>
</div>
</div>
</ng-template>
</ngb-tab>
<ngb-tab [title]="'AbpIdentity::Roles' | abpLocalization">
<ng-template ngbTabContent>
<div class="mt-2">
<div
*ngFor="let roleGroup of roleGroups; let i = index; trackBy: trackByFn"
class="custom-checkbox custom-control mb-2"
>
<input
type="checkbox"
name="Roles[0].IsAssigned"
value="true"
class="custom-control-input"
[attr.id]="'roles-' + i"
[formControl]="roleGroup.controls[roles[i].name]"
/>
<label class="custom-control-label" [attr.for]="'roles-' + i">{{ roles[i].name }}</label>
</ng-template>
</ngb-tab>
<ngb-tab [title]="'AbpIdentity::Roles' | abpLocalization">
<ng-template ngbTabContent>
<div class="mt-2">
<div
*ngFor="let roleGroup of roleGroups; let i = index; trackBy: trackByFn"
class="custom-checkbox custom-control mb-2"
>
<input
type="checkbox"
name="Roles[0].IsAssigned"
value="true"
class="custom-control-input"
[attr.id]="'roles-' + i"
[formControl]="roleGroup.controls[roles[i].name]"
/>
<label class="custom-control-label" [attr.for]="'roles-' + i">{{ roles[i].name }}</label>
</div>
</div>
</div>
</ng-template>
</ngb-tab>
</ngb-tabset>
</div>
</ng-template>
</ngb-tab>
</ngb-tabset>
</form>
</perfect-scrollbar>
</ng-template>
<ng-template #abpFooter>
<button type="button" class="btn btn-secondary" #abpClose>
{{ 'AbpIdentity::Cancel' | abpLocalization }}
</button>
<button type="button" class="btn btn-primary" (click)="save()">
<i class="fa fa-check mr-1"></i> <span>{{ 'AbpIdentity::Save' | abpLocalization }}</span>
</button>
</ng-template>
</abp-modal>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" (click)="modal.close()">
{{ 'AbpIdentity::Cancel' | abpLocalization }}
</button>
<button type="submit" class="btn btn-primary">
<i class="fa fa-check mr-1"></i> <span>{{ 'AbpIdentity::Save' | abpLocalization }}</span>
</button>
</div>
</form>
</ng-template>
<abp-permission-management
[(visible)]="visiblePermissions"
providerName="User"

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

@ -1,27 +1,37 @@
import { Component, TemplateRef, ViewChild, TrackByFunction, OnInit } from '@angular/core';
import { Select, Store } from '@ngxs/store';
import { Observable, combineLatest, Subject } from 'rxjs';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { FormBuilder, FormGroup, Validators, FormArray, AbstractControl } from '@angular/forms';
import { IdentityState } from '../../states/identity.state';
import { Identity } from '../../models/identity';
import { ABP } from "@abp/ng.core";
import { ConfirmationService, Toaster } from "@abp/ng.theme.shared";
import {
Component,
OnInit,
TemplateRef,
TrackByFunction,
ViewChild
} from "@angular/core";
import {
AbstractControl,
FormArray,
FormBuilder,
FormGroup,
Validators
} from "@angular/forms";
import { validatePassword } from "@ngx-validate/core";
import { Select, Store } from "@ngxs/store";
import { combineLatest, Observable, Subject } from "rxjs";
import { debounceTime, filter, map, pluck, take } from "rxjs/operators";
import snq from "snq";
import {
IdentityUpdateUser,
IdentityAddUser,
IdentityDeleteUser,
IdentityGetUserById,
IdentityGetUserRoles,
IdentityGetUsers,
} from '../../actions/identity.actions';
import { pluck, filter, map, take, debounceTime } from 'rxjs/operators';
import { ConfirmationService, Toaster } from '@abp/ng.theme.shared';
import snq from 'snq';
import { IdentityGetUserRoles } from '../../actions/identity.actions';
import { validatePassword } from '@ngx-validate/core';
import { ABP } from '@abp/ng.core';
IdentityUpdateUser
} from "../../actions/identity.actions";
import { Identity } from "../../models/identity";
import { IdentityState } from "../../states/identity.state";
@Component({
selector: 'abp-users',
templateUrl: './users.component.html',
selector: "abp-users",
templateUrl: "./users.component.html"
})
export class UsersComponent implements OnInit {
@Select(IdentityState.getUsers)
@ -30,7 +40,7 @@ export class UsersComponent implements OnInit {
@Select(IdentityState.getUsersTotalCount)
totalCount$: Observable<number>;
@ViewChild('modalContent', { static: false })
@ViewChild("modalContent", { static: false })
modalContent: TemplateRef<any>;
form: FormGroup;
@ -46,24 +56,29 @@ export class UsersComponent implements OnInit {
providerKey: string;
pageQuery: ABP.PageQueryParams = {
sorting: 'userName',
sorting: "userName"
};
isModalVisible: boolean;
loading: boolean = false;
search$ = new Subject<string>();
trackByFn: TrackByFunction<AbstractControl> = (index, item) => Object.keys(item)[0] || index;
trackByFn: TrackByFunction<AbstractControl> = (index, item) =>
Object.keys(item)[0] || index;
get roleGroups(): FormGroup[] {
return snq(() => (this.form.get('roleNames') as FormArray).controls as FormGroup[], []);
return snq(
() => (this.form.get("roleNames") as FormArray).controls as FormGroup[],
[]
);
}
constructor(
private confirmationService: ConfirmationService,
private modalService: NgbModal,
private fb: FormBuilder,
private store: Store,
private store: Store
) {}
ngOnInit() {
@ -78,34 +93,51 @@ export class UsersComponent implements OnInit {
this.form = this.fb.group({
password: [
'',
"",
[
Validators.required,
Validators.maxLength(32),
Validators.minLength(6),
validatePassword(['small', 'capital', 'number', 'special']),
],
validatePassword(["small", "capital", "number", "special"])
]
],
userName: [
this.selected.userName || "",
[Validators.required, Validators.maxLength(256)]
],
email: [
this.selected.email || "",
[Validators.required, Validators.email, Validators.maxLength(256)]
],
name: [this.selected.name || "", [Validators.maxLength(64)]],
surname: [this.selected.surname || "", [Validators.maxLength(64)]],
phoneNumber: [
this.selected.phoneNumber || "",
[Validators.maxLength(16)]
],
lockoutEnabled: [
this.selected.twoFactorEnabled || (this.selected.id ? false : true)
],
twoFactorEnabled: [
this.selected.twoFactorEnabled || (this.selected.id ? false : true)
],
userName: [this.selected.userName || '', [Validators.required, Validators.maxLength(256)]],
email: [this.selected.email || '', [Validators.required, Validators.email, Validators.maxLength(256)]],
name: [this.selected.name || '', [Validators.maxLength(64)]],
surname: [this.selected.surname || '', [Validators.maxLength(64)]],
phoneNumber: [this.selected.phoneNumber || '', [Validators.maxLength(16)]],
lockoutEnabled: [this.selected.twoFactorEnabled || (this.selected.id ? false : true)],
twoFactorEnabled: [this.selected.twoFactorEnabled || (this.selected.id ? false : true)],
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)
)
]
})
)
)
});
}
openModal() {
this.buildForm();
this.modalService.open(this.modalContent);
this.isModalVisible = true;
}
onAdd() {
@ -115,12 +147,15 @@ export class UsersComponent implements OnInit {
}
onEdit(id: string) {
combineLatest([this.store.dispatch(new IdentityGetUserById(id)), this.store.dispatch(new IdentityGetUserRoles(id))])
combineLatest([
this.store.dispatch(new IdentityGetUserById(id)),
this.store.dispatch(new IdentityGetUserRoles(id))
])
.pipe(
filter(([res1, res2]) => res1 && res2),
map(([state, _]) => state),
pluck('IdentityState'),
take(1),
pluck("IdentityState"),
take(1)
)
.subscribe((state: Identity.State) => {
this.selected = state.selectedUser;
@ -134,8 +169,11 @@ export class UsersComponent implements OnInit {
const { roleNames } = this.form.value;
const mappedRoleNames = snq(
() => roleNames.filter(role => !!role[Object.keys(role)[0]]).map(role => Object.keys(role)[0]),
[],
() =>
roleNames
.filter(role => !!role[Object.keys(role)[0]])
.map(role => Object.keys(role)[0]),
[]
);
this.store
@ -144,18 +182,27 @@ export class UsersComponent implements OnInit {
? new IdentityUpdateUser({
...this.form.value,
id: this.selected.id,
roleNames: mappedRoleNames,
roleNames: mappedRoleNames
})
: new IdentityAddUser({
...this.form.value,
roleNames: mappedRoleNames
})
: new IdentityAddUser({ ...this.form.value, roleNames: mappedRoleNames }),
)
.subscribe(() => this.modalService.dismissAll());
.subscribe(() => {
this.isModalVisible = false;
});
}
delete(id: string, userName: string) {
this.confirmationService
.warn('AbpIdentity::UserDeletionConfirmationMessage', 'AbpIdentity::AreYouSure', {
messageLocalizationParams: [userName],
})
.warn(
"AbpIdentity::UserDeletionConfirmationMessage",
"AbpIdentity::AreYouSure",
{
messageLocalizationParams: [userName]
}
)
.subscribe((status: Toaster.Status) => {
if (status === Toaster.Status.confirm) {
this.store.dispatch(new IdentityDeleteUser(id));
@ -172,6 +219,8 @@ export class UsersComponent implements OnInit {
get() {
this.loading = true;
this.store.dispatch(new IdentityGetUsers(this.pageQuery)).subscribe(() => (this.loading = false));
this.store
.dispatch(new IdentityGetUsers(this.pageQuery))
.subscribe(() => (this.loading = false));
}
}

2
npm/ng-packs/packages/identity/src/lib/identity.module.ts

@ -10,6 +10,7 @@ import { UsersComponent } from './components/users/users.component';
import { PermissionManagementModule } from '@abp/ng.permission-management';
import { TableModule } from 'primeng/table';
import { NgxValidateCoreModule } from '@ngx-validate/core';
import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar';
@NgModule({
declarations: [RolesComponent, UsersComponent],
@ -23,6 +24,7 @@ import { NgxValidateCoreModule } from '@ngx-validate/core';
NgbDropdownModule,
PermissionManagementModule,
NgxValidateCoreModule,
PerfectScrollbarModule,
],
})
export class IdentityModule {}

Loading…
Cancel
Save