Fixed issue.

This commit is contained in:
Sk Shaifat Murshed 2025-01-31 18:50:30 +05:30
parent ec91f9ee4f
commit 14eb61b75d
4 changed files with 698 additions and 231 deletions

View File

@ -12,7 +12,7 @@
<p-table [value]="data.items" [paginator]="true" [rows]="5" responsiveLayout="scroll"> <p-table [value]="data.items" [paginator]="true" [rows]="5" responsiveLayout="scroll">
<ng-template pTemplate="header"> <ng-template pTemplate="header">
<tr> <tr>
<th pSortableColumn="name">name <p-sortIcon field="name"></p-sortIcon></th> <th pSortableColumn="name">Role name <p-sortIcon field="name"></p-sortIcon></th>
<th>Actions</th> <th>Actions</th>
</tr> </tr>
@ -22,11 +22,11 @@
<tr> <tr>
<td>{{ role.name }}</td> <td>{{ role.name }}</td>
<td> <td>
<button pButton icon="pi pi-pencil" class="p-button-text p-button-primary" (click)="edit(role.id)"></button> <button pButton icon="pi pi-pencil" class="p-button-text p-button-primary" (click)="edit(role.id)"></button>
<button pButton icon="pi pi-trash" class="p-button-text p-button-danger" (click)="delete(role.id,role.name)"></button> <button pButton icon="pi pi-trash" class="p-button-text p-button-danger" (click)="delete(role.id,role.name)"></button>
<button pButton icon="pi pi-external-link" class="p-button-text p-button-success" (click)="openPermissionsModal(role.name)"></button> <button pButton icon="pi pi-lock" class="p-button-text p-button-success" (click)="openPermissionsModal(role.name)"></button>
</td> </td>
</tr> </tr>
@ -40,19 +40,66 @@
<h3>{{ (selected?.id ? 'AbpIdentity::Edit' : 'AbpIdentity::NewRole') | abpLocalization }}</h3> <h3>{{ (selected?.id ? 'AbpIdentity::Edit' : 'AbpIdentity::NewRole') | abpLocalization }}</h3>
</ng-template> </ng-template>
<ng-template #abpBody> <!-- <ng-template #abpBody>
<form [formGroup]="form" (ngSubmit)="save()" validateOnSubmit> <form [formGroup]="form" (ngSubmit)="save()" validateOnSubmit>
<abp-extensible-form [selectedRecord]="selected"></abp-extensible-form> <abp-extensible-form [selectedRecord]="selected"></abp-extensible-form>
</form> </form>
</ng-template> -->
<ng-template #abpBody>
<form #roleForm="ngForm" (ngSubmit)="save()" validateOnSubmit>
<!-- Name Field -->
<div class="form-group">
<label for="name">Name</label>
<input
id="name"
type="text"
class="form-control"
[(ngModel)]="selected.name"
name="name"
required
#nameCtrl="ngModel"
/>
<small class="text-danger" *ngIf="nameCtrl.invalid && nameCtrl.touched">Name is required</small>
</div>
<!-- Is Default Checkbox -->
<div class="form-check">
<input
id="isDefault"
type="checkbox"
class="form-check-input"
[(ngModel)]="selected.isDefault"
name="isDefault"
/>
<label for="isDefault" class="form-check-label">Default</label>
</div>
<!-- Is Public Checkbox -->
<div class="form-check">
<input
id="isPublic"
type="checkbox"
class="form-check-input"
[(ngModel)]="selected.isPublic"
name="isPublic"
/>
<label for="isPublic" class="form-check-label">Public</label>
</div>
<br>
<abp-button iconClass="fa fa-check" [disabled]="roleForm.invalid" (click)="save()">{{
'AbpIdentity::Save' | abpLocalization
}}</abp-button>
</form>
</ng-template> </ng-template>
<ng-template #abpFooter> <ng-template #abpFooter>
<button type="button" class="btn btn-outline-primary" abpClose> <button type="button" class="btn btn-outline-primary" abpClose>
{{ 'AbpIdentity::Cancel' | abpLocalization }} {{ 'AbpIdentity::Cancel' | abpLocalization }}
</button> </button>
<abp-button iconClass="fa fa-check" [disabled]="form?.invalid" (click)="save()">{{ <!-- <abp-button iconClass="fa fa-check" [disabled]="roleForm?.invalid" (click)="save()">{{
'AbpIdentity::Save' | abpLocalization 'AbpIdentity::Save' | abpLocalization
}}</abp-button> }}</abp-button> -->
</ng-template> </ng-template>
</abp-modal> </abp-modal>

View File

@ -13,7 +13,7 @@ import {
PagedAndSortedResultRequestDto, PagedAndSortedResultRequestDto,
PagedResultDto, PagedResultDto,
} from '@abp/ng.core'; } from '@abp/ng.core';
import { IdentityRoleDto, IdentityRoleService } from '@abp/ng.identity/proxy'; import { IdentityRoleCreateDto, IdentityRoleDto, IdentityRoleService, IdentityRoleUpdateDto } from '@abp/ng.identity/proxy';
import { import {
ThemeSharedModule, ThemeSharedModule,
ConfirmationService, ConfirmationService,
@ -22,7 +22,7 @@ import {
} from '@abp/ng.theme.shared'; } from '@abp/ng.theme.shared';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { Component, inject, Injector, OnInit } from '@angular/core'; import { Component, inject, Injector, OnInit } from '@angular/core';
import { FormsModule, UntypedFormGroup } from '@angular/forms'; import { FormControl, FormGroup, FormsModule, UntypedFormGroup, Validators } from '@angular/forms';
import { ButtonModule } from 'primeng/button'; import { ButtonModule } from 'primeng/button';
import { TableModule } from 'primeng/table'; import { TableModule } from 'primeng/table';
import { finalize } from 'rxjs'; import { finalize } from 'rxjs';
@ -31,6 +31,8 @@ import { NgxDatatableModule } from '@swimlane/ngx-datatable';
import { eIdentityComponents } from '@abp/ng.identity'; import { eIdentityComponents } from '@abp/ng.identity';
import { PermissionManagementModule } from '@abp/ng.permission-management'; import { PermissionManagementModule } from '@abp/ng.permission-management';
import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap'; import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
import { MenuItem } from 'primeng/api';
import { Dropdown, DropdownModule } from 'primeng/dropdown';
@Component({ @Component({
selector: 'app-custom-roles', selector: 'app-custom-roles',
@ -47,7 +49,8 @@ import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
ExtensibleModule, ExtensibleModule,
PermissionManagementModule, PermissionManagementModule,
CoreModule, CoreModule,
NgbNavModule NgbNavModule,
DropdownModule
], ],
templateUrl: './custom-roles.component.html', templateUrl: './custom-roles.component.html',
providers: [ providers: [
@ -87,49 +90,97 @@ export class CustomRolesComponent implements OnInit {
}; };
ngOnInit() { ngOnInit() {
this.hookToQuery(); this.hookToQuery();
} }
// buildForm() {
// const data = new FormPropData(this.injector, this.selected);
// this.form = generateFormFromProps(data);
// }
buildForm() { buildForm() {
const data = new FormPropData(this.injector, this.selected); this.form = new FormGroup({
this.form = generateFormFromProps(data); name: new FormControl(this.selected?.name || '', Validators.required),
isDefault: new FormControl(this.selected?.isDefault || false),
isPublic: new FormControl(this.selected?.isPublic || false)
});
} }
openModal() { openModal() {
this.buildForm(); this.buildForm();
this.isModalVisible = true; this.isModalVisible = true;
} }
add() { add() {
this.selected = {} as IdentityRoleDto; debugger
this.openModal(); // this.selected = {} as IdentityRoleDto;
// this.openModal();
this.selected = { name: '', isDefault: false, isPublic: false } as IdentityRoleDto;
this.isModalVisible = true;
} }
edit(id: string) { edit(id: string) {
debugger debugger
// this.service.get(id).subscribe(res => {
// this.selected = res;
// this.openModal();
// });
this.service.get(id).subscribe(res => { this.service.get(id).subscribe(res => {
this.selected = res; this.selected = res;
this.openModal(); this.isModalVisible = true;
}); });
} }
save() { // save() {
if (!this.form.valid) return; // debugger
this.modalBusy = true; // if (!this.form.valid) return;
// this.modalBusy = true;
const { id } = this.selected || {}; // const { id } = this.selected || {};
(id // (id
? this.service.update(id, { ...this.selected, ...this.form.value }) // ? this.service.update(id, { ...this.selected, ...this.form.value })
: this.service.create(this.form.value) // : this.service.create(this.form.value)
) // )
.pipe(finalize(() => (this.modalBusy = false))) // .pipe(finalize(() => (this.modalBusy = false)))
// .subscribe(() => {
// this.isModalVisible = false;
// this.toasterService.success('AbpUi::SavedSuccessfully');
// this.list.get();
// });
// }
save() {
debugger
if (!this.selected?.name) {
return;
}
this.modalBusy = true;
const { id, name, isDefault, isPublic, concurrencyStamp } = this.selected;
const roleDto = {
name,
isDefault,
isPublic,
concurrencyStamp
};
const saveObservable = id
? this.service.update(id, roleDto) // Update call
: this.service.create(roleDto); // Create call
saveObservable
.pipe(finalize(() => (this.modalBusy = false)))
.subscribe(() => { .subscribe(() => {
this.isModalVisible = false; this.isModalVisible = false;
this.toasterService.success('AbpUi::SavedSuccessfully'); this.toasterService.success('AbpUi::SavedSuccessfully');
this.list.get(); this.list.get();
}); });
} }
delete(id: string, name: string) { delete(id: string, name: string) {
this.confirmationService this.confirmationService
.warn('AbpIdentity::RoleDeletionConfirmationMessage', 'AbpIdentity::AreYouSure', { .warn('AbpIdentity::RoleDeletionConfirmationMessage', 'AbpIdentity::AreYouSure', {

View File

@ -8,24 +8,29 @@
</div> --> </div> -->
<abp-page [title]="'AbpIdentity::Users' | abpLocalization" [toolbar]="data.items"> <abp-page [title]="'AbpIdentity::Users' | abpLocalization" [toolbar]="data.items">
<div id="identity-roles-wrapper" class="card"> <div id="identity-roles-wrapper" class="card">
<div class="card-body"> <div class="card-body">
<div id="data-tables-table-filter" class="data-tables-filter mb-3"> <div id="data-tables-table-filter" class="data-tables-filter mb-3">
<div class="flex justify-content-between align-items-center mb-3"> <div class="flex justify-content-between align-items-center mb-3">
<button pButton icon="pi pi-plus" label="Add User" class="p-button-success" (click)="add()"></button> <button
</div> pButton
<div class="input-group"> icon="pi pi-plus"
<input label="Add User"
type="search" class="p-button-success"
class="form-control" (click)="add()"
[placeholder]="'AbpUi::PagerSearch' | abpLocalization" ></button>
[(ngModel)]="list.filter"
/>
</div>
</div> </div>
<div class="input-group">
<input
type="search"
class="form-control"
[placeholder]="'AbpUi::PagerSearch' | abpLocalization"
[(ngModel)]="list.filter"
/>
</div>
</div>
<!-- <!--
<abp-extensible-table <abp-extensible-table
[data]="data.items" [data]="data.items"
@ -33,115 +38,295 @@
[list]="list" [list]="list"
></abp-extensible-table> --> ></abp-extensible-table> -->
<p-table [value]="data.items" [paginator]="true" [rows]="5" responsiveLayout="scroll"> <p-table
<ng-template pTemplate="header"> [value]="data.items"
<tr> [tableStyle]="{ 'min-width': '60rem' }"
<th pSortableColumn="userName">Username <p-sortIcon field="userName"></p-sortIcon></th> [paginator]="true"
<th pSortableColumn="name">First Name <p-sortIcon field="name"></p-sortIcon></th> [rows]="5"
<th pSortableColumn="surname">Last Name <p-sortIcon field="surname"></p-sortIcon></th> responsiveLayout="scroll"
<th pSortableColumn="email">Email <p-sortIcon field="email"></p-sortIcon></th> >
<th>Status</th> <ng-template pTemplate="header">
<th>Actions</th> <tr>
</tr> <th pSortableColumn="userName">Username <p-sortIcon field="userName"></p-sortIcon></th>
</ng-template> <th pSortableColumn="name">First Name <p-sortIcon field="name"></p-sortIcon></th>
<th pSortableColumn="surname">Last Name <p-sortIcon field="surname"></p-sortIcon></th>
<ng-template pTemplate="body" let-user> <th pSortableColumn="email">Email <p-sortIcon field="email"></p-sortIcon></th>
<tr> <th pSortableColumn="Phone">Phone No <p-sortIcon field="Phone"></p-sortIcon></th>
<td>{{ user.userName }}</td> <th>Status</th>
<td>{{ user.name }}</td> <th>Actions</th>
<td>{{ user.surname }}</td> </tr>
<td>{{ user.email }}</td> </ng-template>
<td>
<p-tag [value]="user.isActive ? 'Active' : 'Inactive'" [severity]="user.isActive ? 'success' : 'danger'"></p-tag>
</td>
<td>
<button pButton icon="pi pi-pencil" class="p-button-text p-button-primary" (click)="edit(user.id)"></button>
<button pButton icon="pi pi-trash" class="p-button-text p-button-danger" (click)="delete(user.id,user.userName)"></button>
<button pButton icon="pi pi-external-link" class="p-button-text p-button-success" (click)="openPermissionsModal(user.name,user.name)"></button>
</td> <ng-template pTemplate="body" let-user>
</tr> <tr>
</ng-template> <td>{{ user.userName }}</td>
</p-table> <td>{{ user.name }}</td>
<td>{{ user.surname }}</td>
<td>{{ user.email }}</td>
</div> <td>{{ user.phoneNumber }}</td>
<td>
<p-tag
[value]="user.isActive ? 'Active' : 'Inactive'"
[severity]="user.isActive ? 'success' : 'danger'"
></p-tag>
</td>
<td>
<div class="btn-group" dropdown placement="bottom left" container="body">
<p-splitButton
label="Actions"
icon="pi pi-cog"
class="p-button-sm p-button-primary"
[model]="actionItems"
(onClick)="editUser(user.id)"
>
</p-splitButton>
</div>
<!-- <button
pButton
icon="pi pi-pencil"
class="p-button-text p-button-primary"
(click)="edit(user.id)"
></button>
<button
pButton
icon="pi pi-trash"
class="p-button-text p-button-danger"
(click)="delete(user.id, user.userName)"
></button>
<button
pButton
icon="pi pi-lock"
class="p-button-text p-button-success"
(click)="openPermissionsModal(user.id, user.userName)"
></button> -->
<!-- <div class="btn-group" dropdown placement="bottom left" container="body">
<button
id="dropdownButton"
type="button"
class="btn btn-primary btn-sm dropdown-toggle"
dropdownToggle
aria-controls="dropdownMenu"
(click)="toggleDropdown()"
>
<i class="fa fa-cog"></i>
<span class="caret"></span>
Actions
</button>
<ul
id="dropdownMenu"
#dropdownMenu
class="dropdown-menu"
role="menu"
aria-labelledby="dropdownButton"
>
<li role="menuitem" tabindex="0">
<a
#firstDropdownItem
class="dropdown-item"
href="javascript:;"
(click)="edit(user.id)"
>
Edit
</a>
</li>
</ul>
</div> -->
</td>
</tr>
</ng-template>
</p-table>
</div> </div>
</div>
<abp-modal [(visible)]="isModalVisible" [busy]="modalBusy">
<ng-template #abpHeader> <abp-modal [(visible)]="isModalVisible" [busy]="modalBusy">
<h3>{{ (selected?.id ? 'AbpIdentity::Edit' : 'AbpIdentity::NewUser') | abpLocalization }}</h3> <ng-template #abpHeader>
</ng-template> <h3>
{{ (selected?.id ? 'AbpIdentity::EditUser' : 'AbpIdentity::NewUser') | abpLocalization }}
<ng-template #abpBody> </h3>
@if (form) { </ng-template>
<form [formGroup]="form" (ngSubmit)="save()">
<ul ngbNav #nav="ngbNav" class="nav-tabs"> <ng-template #abpBody>
<li ngbNavItem> <form #userForm="ngForm" (ngSubmit)="save(userForm)">
<a ngbNavLink>{{ 'AbpIdentity::UserInformations' | abpLocalization }}</a> <!-- User Information Tab -->
<ng-template ngbNavContent> <ul ngbNav #nav="ngbNav" class="nav-tabs">
<abp-extensible-form [selectedRecord]="selected"></abp-extensible-form> <li ngbNavItem>
</ng-template> <a ngbNavLink>{{ 'AbpIdentity::UserInformations' | abpLocalization }}</a>
</li> <ng-template ngbNavContent>
<div class="form-group">
<li ngbNavItem> <label for="userName">{{ 'User Name' | abpLocalization }}</label>
<a ngbNavLink>{{ 'AbpIdentity::Roles' | abpLocalization }}</a> <input
<ng-template ngbNavContent> id="userName"
@for (roleGroup of roleGroups; track $index; let i = $index) { type="text"
<div class="form-check mb-2"> class="form-control"
<abp-checkbox [(ngModel)]="selected.userName"
*abpReplaceableTemplate="{ name="userName"
inputs: { required
checkboxId: 'roles-' + i, #userName="ngModel"
label: roles[i].name, />
formControl: roleGroup.controls[roles[i].name] <div *ngIf="userName.invalid && userName.touched" class="text-danger">
}, User Name is required
componentKey: inputKey </div>
}" </div>
[checkboxId]="'roles-' + i"
[formControl]="roleGroup.controls[roles[i].name]" <!-- Password -->
[label]="roles[i].name" <div class="form-group" *ngIf="!selected.id">
> <label for="password">Password</label>
</abp-checkbox> <input
</div> id="password"
} type="password"
</ng-template> class="form-control"
</li> [(ngModel)]="password"
</ul> name="password"
<div class="mt-2 fade-in-top" [ngbNavOutlet]="nav"></div> required
</form> #passwordField="ngModel"
} @else { />
<div class="text-center"><i class="fa fa-pulse fa-spinner" aria-hidden="true"></i></div> <div *ngIf="passwordField.invalid && passwordField.touched" class="text-danger">
} Password is required
</ng-template> </div>
</div>
<ng-template #abpFooter>
<button type="button" class="btn btn-outline-primary" abpClose> <!-- Name -->
{{ 'AbpIdentity::Cancel' | abpLocalization }} <div class="form-group">
</button> <label for="name">{{ 'Name' | abpLocalization }}</label>
<abp-button iconClass="fa fa-check" [disabled]="form?.invalid" (click)="save()">{{ <input
id="name"
type="text"
class="form-control"
[(ngModel)]="selected.name"
name="name"
#name="ngModel"
/>
</div>
<!-- Surname -->
<div class="form-group">
<label for="surname">{{ 'Surname' | abpLocalization }}</label>
<input
id="surname"
type="text"
class="form-control"
[(ngModel)]="selected.surname"
name="surname"
#surname="ngModel"
/>
</div>
<!-- Email -->
<div class="form-group">
<label for="email">{{ 'Email' | abpLocalization }}</label>
<input
id="email"
type="email"
class="form-control"
[(ngModel)]="selected.email"
name="email"
required
#email="ngModel"
/>
<div *ngIf="email.invalid && email.touched" class="text-danger">
Valid Email is required
</div>
</div>
<!-- Phone Number -->
<div class="form-group">
<label for="phoneNumber">{{ 'Phone Number' | abpLocalization }}</label>
<input
id="phoneNumber"
type="text"
class="form-control"
[(ngModel)]="selected.phoneNumber"
name="phoneNumber"
#phoneNumber="ngModel"
/>
</div>
<!-- Active Account (Checkbox) -->
<div class="form-check">
<input
id="isActive"
type="checkbox"
class="form-check-input"
[(ngModel)]="selected.isActive"
name="isActive"
/>
<label for="isActive" class="form-check-label">{{
'Active' | abpLocalization
}}</label>
</div>
<!-- Lockout Enabled (Checkbox) -->
<div class="form-check">
<input
id="lockoutEnabled"
type="checkbox"
class="form-check-input"
[(ngModel)]="selected.lockoutEnabled"
name="lockoutEnabled"
/>
<label for="lockoutEnabled" class="form-check-label">{{
'Lockout Enabled' | abpLocalization
}}</label>
</div>
</ng-template>
</li>
<!-- Roles Tab -->
<li ngbNavItem>
<a ngbNavLink>{{ 'AbpIdentity::Roles' | abpLocalization }}</a>
<ng-template ngbNavContent>
<div *ngFor="let role of roles; let i = index">
<div class="form-check mb-2">
<label class="form-check-label">
<input
type="checkbox"
class="form-check-input"
[(ngModel)]="role.selected"
name="role-{{ i }}"
/>
{{ role.name }}
</label>
</div>
</div>
</ng-template>
</li>
</ul>
<div class="mt-2 fade-in-top" [ngbNavOutlet]="nav"></div>
<div class="mt-3">
<button type="submit" class="btn btn-primary" [disabled]="userForm.invalid">Save</button>
</div>
</form>
</ng-template>
<ng-template #abpFooter>
<button type="button" class="btn btn-outline-primary" abpClose>
{{ 'AbpIdentity::Cancel' | abpLocalization }}
</button>
<!-- <abp-button iconClass="fa fa-check" [disabled]="form?.invalid" (click)="save()">{{
'AbpIdentity::Save' | abpLocalization 'AbpIdentity::Save' | abpLocalization
}}</abp-button> }}</abp-button> -->
</ng-template> </ng-template>
</abp-modal> </abp-modal>
<abp-permission-management <abp-permission-management
#abpPermissionManagement="abpPermissionManagement" #abpPermissionManagement="abpPermissionManagement"
*abpReplaceableTemplate=" *abpReplaceableTemplate="
{ {
inputs: { inputs: {
providerName: { value: 'U' }, providerName: { value: 'U' },
providerKey: { value: providerKey }, providerKey: { value: providerKey },
visible: { value: visiblePermissions, twoWay: true } visible: { value: visiblePermissions, twoWay: true }
}, },
outputs: { visibleChange: onVisiblePermissionChange }, outputs: { visibleChange: onVisiblePermissionChange },
componentKey: permissionManagementKey componentKey: permissionManagementKey
}; };
let init = initTemplate let init = initTemplate
" "
[entityDisplayName]="entityDisplayName" [entityDisplayName]="entityDisplayName"
(abpInit)="init(abpPermissionManagement)" (abpInit)="init(abpPermissionManagement)"
> >
</abp-permission-management> </abp-permission-management>
</abp-page> </abp-page>

View File

@ -1,29 +1,83 @@
import { FormPropData,EXTENSIONS_IDENTIFIER ,generateFormFromProps, ExtensibleModule} from '@abp/ng.components/extensible'; import {
FormPropData,
EXTENSIONS_IDENTIFIER,
generateFormFromProps,
ExtensibleModule,
} from '@abp/ng.components/extensible';
import { PageModule } from '@abp/ng.components/page'; import { PageModule } from '@abp/ng.components/page';
import { CoreModule, ListResultDto, ListService, LocalizationModule, PagedResultDto } from '@abp/ng.core'; import {
CoreModule,
ListResultDto,
ListService,
LocalizationModule,
PagedResultDto,
} from '@abp/ng.core';
import { eIdentityComponents } from '@abp/ng.identity'; import { eIdentityComponents } from '@abp/ng.identity';
import { GetIdentityUsersInput, IdentityRoleDto, IdentityUserDto, IdentityUserService } from '@abp/ng.identity/proxy'; import {
GetIdentityUsersInput,
IdentityRoleDto,
IdentityUserDto,
IdentityUserService,
IdentityUserUpdateDto,
} from '@abp/ng.identity/proxy';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { Component, inject, Injector, OnInit, TemplateRef, TrackByFunction, ViewChild } from '@angular/core'; import {
import { AbstractControl, FormsModule, UntypedFormArray, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; Component,
ElementRef,
HostListener,
inject,
Injector,
OnInit,
TemplateRef,
TrackByFunction,
ViewChild,
} from '@angular/core';
import {
AbstractControl,
FormsModule,
NgForm,
UntypedFormArray,
UntypedFormBuilder,
UntypedFormGroup,
} from '@angular/forms';
import { ButtonModule } from 'primeng/button'; import { ButtonModule } from 'primeng/button';
import { TableModule } from 'primeng/table'; import { TableModule } from 'primeng/table';
import { Confirmation, eFormComponets, ThemeSharedModule,ToasterService ,ConfirmationService} from '@abp/ng.theme.shared'; import {
Confirmation,
eFormComponets,
ThemeSharedModule,
ToasterService,
ConfirmationService,
} from '@abp/ng.theme.shared';
import { finalize, switchMap, tap } from 'rxjs'; import { finalize, switchMap, tap } from 'rxjs';
import { ePermissionManagementComponents, PermissionManagementModule } from '@abp/ng.permission-management'; import {
ePermissionManagementComponents,
PermissionManagementModule,
} from '@abp/ng.permission-management';
import { NgxDatatableModule } from '@swimlane/ngx-datatable'; import { NgxDatatableModule } from '@swimlane/ngx-datatable';
import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap'; import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
import { PaginatorModule } from 'primeng/paginator'; import { PaginatorModule } from 'primeng/paginator';
import { TagModule } from 'primeng/tag'; // For active/inactive status import { TagModule } from 'primeng/tag'; // For active/inactive status
import { SplitButtonModule } from 'primeng/splitbutton';
@Component({ @Component({
selector: 'app-custom-users', selector: 'app-custom-users',
standalone: true, standalone: true,
imports: [CommonModule,FormsModule,TableModule,ButtonModule,PageModule,LocalizationModule,ThemeSharedModule,NgxDatatableModule,ExtensibleModule, imports: [
PermissionManagementModule, CommonModule,
CoreModule, FormsModule,
NgbNavModule, TableModule,
PaginatorModule,TagModule ButtonModule,
PageModule,
LocalizationModule,
ThemeSharedModule,
NgxDatatableModule,
ExtensibleModule,
PermissionManagementModule,
CoreModule,
NgbNavModule,
PaginatorModule,
TagModule,SplitButtonModule
], ],
templateUrl: './custom-users.component.html', templateUrl: './custom-users.component.html',
providers: [ providers: [
@ -33,15 +87,16 @@ import { TagModule } from 'primeng/tag'; // For active/inactive status
useValue: eIdentityComponents.Users, useValue: eIdentityComponents.Users,
}, },
], ],
styleUrl: './custom-users.component.scss' styleUrl: './custom-users.component.scss',
}) })
export class CustomUsersComponent implements OnInit{ export class CustomUsersComponent implements OnInit {
protected readonly list = inject(ListService<GetIdentityUsersInput>); protected readonly list = inject(ListService<GetIdentityUsersInput>);
protected readonly confirmationService = inject(ConfirmationService); protected readonly confirmationService = inject(ConfirmationService);
protected readonly service = inject(IdentityUserService); protected readonly service = inject(IdentityUserService);
protected readonly toasterService = inject(ToasterService); protected readonly toasterService = inject(ToasterService);
private readonly fb = inject(UntypedFormBuilder); private readonly fb = inject(UntypedFormBuilder);
private readonly injector = inject(Injector); private readonly injector = inject(Injector);
@ViewChild('firstDropdownItem') firstDropdownItem: ElementRef;
data: PagedResultDto<IdentityUserDto> = { items: [], totalCount: 0 }; data: PagedResultDto<IdentityUserDto> = { items: [], totalCount: 0 };
@ -49,12 +104,13 @@ export class CustomUsersComponent implements OnInit{
modalContent!: TemplateRef<any>; modalContent!: TemplateRef<any>;
form!: UntypedFormGroup; form!: UntypedFormGroup;
password:string;
selected?: IdentityUserDto; selected?: IdentityUserDto;
selectedUserRoles?: IdentityRoleDto[]; selectedUserRoles?: IdentityRoleDto[];
roles?: IdentityRoleDto[]; // roles?: IdentityRoleDto[];
roles: (IdentityRoleDto & { selected: boolean })[] = []; // Use intersection type to add 'selected'
visiblePermissions = false; visiblePermissions = false;
@ -71,8 +127,32 @@ export class CustomUsersComponent implements OnInit{
inputKey = eFormComponets.FormCheckboxComponent; inputKey = eFormComponets.FormCheckboxComponent;
trackByFn: TrackByFunction<AbstractControl> = (index, item) => Object.keys(item)[0] || index; trackByFn: TrackByFunction<AbstractControl> = (index, item) => Object.keys(item)[0] || index;
isDropdownOpen = false;
toggleDropdown() {
this.isDropdownOpen = !this.isDropdownOpen;
// After the dropdown is shown, focus the first item in the dropdown
setTimeout(() => {
if (this.firstDropdownItem) {
this.firstDropdownItem.nativeElement.focus();
}
}, 100); // Delay to ensure dropdown is rendered
}
closeDropdown() {
this.isDropdownOpen = false;
}
actionItems = [
{ label: 'Edit', icon: 'pi pi-pencil', command: () => this.edit("") },
{ label: 'Delete', icon: 'pi pi-trash', command: () => this.delete("","") },
// { label: 'Permissions', icon: 'pi pi-shield', command: () => this.openPermissionsModal("") },
];
onVisiblePermissionChange = (event: boolean) => { onVisiblePermissionChange = (event: boolean) => {
debugger
this.visiblePermissions = event; this.visiblePermissions = event;
}; };
@ -83,87 +163,189 @@ export class CustomUsersComponent implements OnInit{
ngOnInit() { ngOnInit() {
this.hookToQuery(); this.hookToQuery();
} }
formValid() {
return true;
}
// buildForm() {
// debugger
// const data = new FormPropData(this.injector, this.selected);
// this.form = generateFormFromProps(data);
// this.service.getAssignableRoles().subscribe(({ items }) => {
// this.roles = items;
// if (this.roles) {
// this.form.addControl(
// 'roleNames',
// this.fb.array(
// this.roles.map(role =>
// this.fb.group({
// [role.name as string]: [
// this.selected?.id
// ? !!this.selectedUserRoles?.find(userRole => userRole.id === role.id)
// : role.isDefault,
// ],
// }),
// ),
// ),
// );
// }
// });
// }
// openModal() {
// this.buildForm();
// this.isModalVisible = true;
// }
// add() {
// debugger
// this.selected = {} as IdentityUserDto;
// this.selectedUserRoles = [] as IdentityRoleDto[];
// this.openModal();
// }
// edit(id: string) {
// debugger
// this.service
// .get(id)
// .pipe(
// tap(user => (this.selected = user)),
// switchMap(() => this.service.getRoles(id)),
// )
// .subscribe(userRole => {
// debugger
// this.selectedUserRoles = userRole.items || [];
// this.openModal();
// });
// }
// save() {
// if (!this.form.valid || this.modalBusy) return;
// this.modalBusy = true;
// const { roleNames = [] } = this.form.value;
// const mappedRoleNames =
// roleNames
// .filter((role: { [key: string]: any }) => !!role[Object.keys(role)[0]])
// .map((role: { [key: string]: any }) => Object.keys(role)[0]) || [];
// const { id } = this.selected || {};
// (id
// ? this.service.update(id, {
// ...this.selected,
// ...this.form.value,
// roleNames: mappedRoleNames,
// })
// : this.service.create({ ...this.form.value, roleNames: mappedRoleNames })
// )
// .pipe(finalize(() => (this.modalBusy = false)))
// .subscribe(() => {
// this.isModalVisible = false;
// this.toasterService.success('AbpUi::SavedSuccessfully');
// this.list.get();
// });
// }
buildForm() { buildForm() {
debugger
const data = new FormPropData(this.injector, this.selected);
this.form = generateFormFromProps(data);
this.service.getAssignableRoles().subscribe(({ items }) => { this.service.getAssignableRoles().subscribe(({ items }) => {
this.roles = items; this.roles = items.map(role => ({
if (this.roles) { ...role,
this.form.addControl( selected: this.selectedUserRoles.some(userRole => userRole.id === role.id),
'roleNames', }));
this.fb.array(
this.roles.map(role => // Initialize the selected roles based on existing data for selected user
this.fb.group({ if (this.selected?.id) {
[role.name as string]: [ this.roles.forEach(role => {
this.selected?.id role.selected = this.selectedUserRoles.some(userRole => userRole.id === role.id);
? !!this.selectedUserRoles?.find(userRole => userRole.id === role.id) });
: role.isDefault, } else {
], // Default values when creating a new user
}), this.roles.forEach(role => {
), role.selected = role.isDefault;
), });
);
} }
}); });
} }
openModal() { openModal() {
this.buildForm(); this.loadRoles(); // Load roles when modal opens
this.isModalVisible = true; this.isModalVisible = true;
} }
loadRoles() {
this.service.getAssignableRoles().subscribe(({ items }) => {
this.roles = items.map(role => ({
...role, // spread IdentityRoleDto properties
selected: false, // Initially no role is selected
}));
});
}
add() { add() {
debugger
this.selected = {} as IdentityUserDto; this.selected = {} as IdentityUserDto;
this.selectedUserRoles = [] as IdentityRoleDto[]; this.selectedUserRoles = [] as IdentityRoleDto[];
this.password = ''; // Store password separately
this.openModal(); this.openModal();
} }
edit(id: string) { edit(id: string) {
debugger
this.service this.service
.get(id) .get(id)
.pipe( .pipe(finalize(() => this.buildForm()))
tap(user => (this.selected = user)), .subscribe(user => {
switchMap(() => this.service.getRoles(id)), this.selected = user;
) this.service.getRoles(id).subscribe(userRoles => {
.subscribe(userRole => { this.selectedUserRoles = userRoles.items || [];
debugger });
this.selectedUserRoles = userRole.items || [];
this.openModal();
}); });
this.openModal();
} }
save() { // Save user data (either create or update)
if (!this.form.valid || this.modalBusy) return; save(form: NgForm) {
debugger;
if (this.modalBusy || form.invalid) return;
this.modalBusy = true; this.modalBusy = true;
const { roleNames = [] } = this.form.value; // Prepare roleNames array
const mappedRoleNames = // Prepare roleNames array
roleNames const selectedRoleNames = this.roles
.filter((role: { [key: string]: any }) => !!role[Object.keys(role)[0]]) .filter(role => role.selected) // Only include selected roles
.map((role: { [key: string]: any }) => Object.keys(role)[0]) || []; .map(role => role.name); // Extract role names
const { id } = this.selected || {}; // Create user payload
(id const userPayload: any = {
? this.service.update(id, { userName: this.selected.userName,
...this.selected, name: this.selected.name,
...this.form.value, surname: this.selected.surname,
roleNames: mappedRoleNames, email: this.selected.email,
}) phoneNumber: this.selected.phoneNumber,
: this.service.create({ ...this.form.value, roleNames: mappedRoleNames }) isActive: this.selected.isActive,
) lockoutEnabled: this.selected.lockoutEnabled,
.pipe(finalize(() => (this.modalBusy = false))) roleNames: selectedRoleNames, // Include selected roles
.subscribe(() => {
this.isModalVisible = false; };
this.toasterService.success('AbpUi::SavedSuccessfully');
this.list.get(); // Only include password if creating a new user
}); if (!this.selected.id && this.password) {
userPayload.password = this.password;
}
// Handle create or update
const saveObservable = this.selected.id
? this.service.update(this.selected.id, userPayload) // Update if id exists
: this.service.create(userPayload); // Create if no id
saveObservable.pipe(finalize(() => (this.modalBusy = false))).subscribe(() => {
this.isModalVisible = false;
this.toasterService.success('AbpUi::SavedSuccessfully');
this.list.get(); // Reload the list if needed
});
}
private getRoleNames() {
return this.roles.filter(role => role.selected).map(role => role.name);
} }
delete(id: string, userName: string) { delete(id: string, userName: string) {
@ -191,17 +373,19 @@ export class CustomUsersComponent implements OnInit{
// this.list.hookToQuery(query => this.service.getList(query)).subscribe(res => (this.data = res)); // this.list.hookToQuery(query => this.service.getList(query)).subscribe(res => (this.data = res));
// } // }
private hookToQuery() { private hookToQuery() {
this.list.hookToQuery(query => { this.list
console.log('Query:', query); // Log the query .hookToQuery(query => {
return this.service.getList(query); console.log('Query:', query); // Log the query
}).subscribe(res => { return this.service.getList(query);
debugger })
this.data = res; .subscribe(res => {
}); debugger;
this.data = res;
});
} }
openPermissionsModal(providerKey: string, entityDisplayName?: string) { openPermissionsModal(providerKey: string, entityDisplayName?: string) {
debugger debugger;
this.providerKey = providerKey; this.providerKey = providerKey;
this.entityDisplayName = entityDisplayName; this.entityDisplayName = entityDisplayName;
setTimeout(() => { setTimeout(() => {