Merge pull request 'setup-user updated' (#35) from mazdak/UX-1985 into dev-pending-01-01-2026

Reviewed-on: https://ct.mfsys.com.pk/aConnect/aConnect-UX/pulls/35
mazdak/UX-2025
Naeem Ullah 3 weeks ago
commit 66c51a9e70

@ -1,95 +0,0 @@
import { Injectable } from '@angular/core';
import { SetupUser } from '../models/user';
import { BehaviorSubject, Observable } from 'rxjs';
import { URIKey } from '../utils/uri-enums';
import { URIService } from '../app.uri';
import { HttpURIService } from '../app.http.uri.service';
import { HttpParams } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class UserSetupService {
private usersSubject = new BehaviorSubject<SetupUser[]>([]);
private currentPageSubject = new BehaviorSubject<number>(1);
private totalCountSubject = new BehaviorSubject<number>(0);
private itemsPerPageSubject = new BehaviorSubject<number>(5);
users$ = this.usersSubject.asObservable();
currentPage$ = this.currentPageSubject.asObservable();
totalCount$ = this.totalCountSubject.asObservable();
itemsPerPage$ = this.itemsPerPageSubject.asObservable();
constructor(private httpURIService: HttpURIService, private uriService: URIService) { }
loadUsers(): void {
this.uriService.canSubscribe.subscribe(can => {
if (can) {
this.httpURIService
.requestGET<any>(URIKey.GET_ALL_USERS)
.subscribe({
next: (res) => {
const users = Array.isArray(res) ? res : res?.data;
this.usersSubject.next(users ?? []);
this.totalCountSubject.next(users.length);
},
error: (err) => console.error(err)
});
}
});
}
setItemsPerPage(itemsPerPage: number): void {
this.itemsPerPageSubject.next(itemsPerPage);
this.currentPageSubject.next(1);
}
nextPage(): void {
const totalPages = this.getTotalPages();
const currentPage = this.currentPageSubject.value;
if (currentPage < totalPages) {
this.currentPageSubject.next(currentPage + 1);
}
}
previousPage(): void {
const currentPage = this.currentPageSubject.value;
if (currentPage > 1) {
this.currentPageSubject.next(currentPage - 1);
}
}
goToPage(page: number): void {
const totalPages = this.getTotalPages();
if (page > 0 && page <= totalPages) {
this.currentPageSubject.next(page);
}
}
getTotalPages(): number {
const totalCount = this.totalCountSubject.value;
const itemsPerPage = this.itemsPerPageSubject.value;
return Math.ceil(totalCount / itemsPerPage);
}
addUser(payload: SetupUser): Observable<SetupUser> {
return this.httpURIService.requestPOST<SetupUser>(URIKey.CREATE_USER, payload);
}
getUserById(userId: any){
const params = new HttpParams().set('userId', userId)
return this.httpURIService.requestGET(URIKey.GET_USER_BY_ID, params);
}
deleteUser(userId: any){
const params = new HttpParams().set('userId', userId)
console.log("params success",params)
return this.httpURIService.requestDELETE(URIKey.DELETE_USER, params)
}
}

@ -163,7 +163,7 @@
<div class="container-fluid">
<div class="col-xl-12 mt-4">
<div class="card border">
<div class="card-body">
<div class="card-body" *ngIf="renewalDataExpanded && allItems.length; else noRecordsFound">
<div class="table-section">
<div class="row">
<div class="col-lg-12">
@ -175,12 +175,11 @@
<div class="search-box">
<input type="text" class="form-control form-control-sm"
[(ngModel)]="searchText"
(ngModelChange)="onSearch($event)"
placeholder="{{ 'search' | translate }}">
<i class="fas fa-search search-icon"></i>
</div>
<i class="materialdesignicons">
<ng-container *ngIf="renewalDataExpanded; else collapsedIcon">
<i class="materialdesignicons" (click)="toggleTableCard()">
<ng-container *ngIf="userSetupDataExpanded; else collapsedIcon">
<i class="dripicons-chevron-up float-end"></i>
</ng-container>
<ng-template #collapsedIcon>
@ -189,7 +188,7 @@
</i>
</div>
</div>
<div class="card-body">
<div class="card-body" *ngIf="userSetupDataExpanded && allItems.length; else noRecordsFound">
<div class="table-responsive">
<table class="table mb-0 border">
<thead class="table-light">
@ -200,30 +199,27 @@
</tr>
</thead>
<tbody>
<tr *ngFor="
let item of (
(users$ | async) ?? []
| userFilter: searchText
).slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage)
">
<tr *ngFor="let item of (allItems | tableFilter: searchText : ['userId', 'userFullname']).slice((currentPage-1)*itemsPerPage, currentPage*itemsPerPage)">
<td>{{ item.userId }}</td>
<td>{{ item.userFullname }}</td>
<td>{{ item.userId }}</td>
<td>{{ item.userFullname }}</td>
<td>
<div class="d-flex justify-content-center gap-2">
<button class="btn btn-info btn-sm" title="View" (click)="onView(item.userId)">
<i class="mdi mdi-eye-outline"></i>
</button>
<td>
<div class="d-flex justify-content-center gap-2">
<button *ngIf="buttonPermissions?.delete" class="btn btn-danger btn-sm" title="Delete" (click)="onDelete(item.userId)">
<i class="fas fa-trash-alt"></i>
</button>
<button class="btn btn-info btn-sm" title="View" (click)="onView(item.userId)">
<i class="mdi mdi-eye-outline"></i>
</button>
</div>
</td>
<button *ngIf="buttonPermissions?.delete" class="btn btn-danger btn-sm" title="Delete"
(click)="onDelete(item.userId)">
<i class="fas fa-trash-alt"></i>
</button>
</div>
</td>
</tr>
</tbody>
@ -235,16 +231,19 @@
bindLabel="label"
bindValue="value"
[(ngModel)]="itemsPerPage"
(change)="onPageSizeChange(itemsPerPage)"
(change)="itemsPerPageChanged()"
[searchable]="false"
[clearable]="false"
[dropdownPosition]="'top'">
</ng-select>
</div>
<div class="text-muted">
{{ 'page' | translate }} {{ currentPage }} {{ 'of' | translate }} {{ getTotalPages() }} ({{ totalCount }} {{ 'totalItems' | translate }})
</div>
<div class="text-muted" *ngIf="allItems.length > 1">
{{'page' | translate}} {{currentPage}} {{'of' |
translate}} {{totalPages()}} ({{allItems.length}}
{{'totalItems' | translate}})
</div>
<div class="btn-group">
<button class="btn btn-primary waves-effect waves-light" (click)="previousPage()">
@ -270,3 +269,8 @@
</div>
</div>
</div>
<ng-template #noRecordsFound>
<div *ngIf="!isLoading && allItems.length === 0" class="text-center text-muted mt-3">
<p>{{'noUserDetailsFound' | translate}}</p>
</div>
</ng-template>

@ -5,22 +5,24 @@ import { NgSelectModule } from '@ng-select/ng-select';
import { TranslateModule } from '@ngx-translate/core';
import { pageSizeOptions } from '../../utils/app.constants';
import { SetupUser } from '../../models/user';
import { UserSetupService } from '../../services/user-setup.service';
import { UserFilterPipe } from '../../shared/pipes/userFilterPipe';
import { FormBuilder, Validators, FormGroup } from '@angular/forms';
import { ButtonManagementService } from '../../services/button-management.service';
import { StorageService } from '../../shared/services/storage.service';
import { TableFilterPipe } from '../../shared/pipes/table-filter.pipe';
import { URIKey } from '../../utils/uri-enums';
import { HttpParams } from '@angular/common/http';
import { HttpURIService } from '../../app.http.uri.service';
@Component({
selector: 'app-setup-user',
standalone: true,
imports: [TranslateModule, ReactiveFormsModule, FormsModule, CommonModule, NgSelectModule, UserFilterPipe],
imports: [TranslateModule, ReactiveFormsModule, FormsModule, CommonModule, NgSelectModule, TableFilterPipe],
templateUrl: './setup-user.component.html',
styleUrl: './setup-user.component.scss'
})
export class SetupUserComponent implements OnInit {
userForm!: FormGroup;
showForm = false;
selectedUserId!: any;
@ -30,11 +32,16 @@ export class SetupUserComponent implements OnInit {
currentPage: number = 1;
pageSizeOptions = pageSizeOptions
itemsPerPage: number = 5;
searchText: string = '';
pagedItems: any[] = [];
searchText: any = '';
renewalDataExpanded: boolean = true;
totalCount: number = 0;
mode: 'edit' | 'view' = 'view';
userSetupDataExpanded: boolean = true
buttonPermissions: any;
isLoading: boolean = false;
setupUserList: SetupUser[] = [];
roleOptions = [
{ label: 'Admin', value: 'ADMIN' },
{ label: 'User', value: 'USER' }
@ -42,41 +49,41 @@ export class SetupUserComponent implements OnInit {
constructor(
private userService: UserSetupService,
private fb: FormBuilder,
private buttonManagementService: ButtonManagementService,
private storageService: StorageService
private storageService: StorageService,
private httpService: HttpURIService
){}
get users$(){
return this.userService.users$;
}
onSearch(value: string): void {
this.searchText = value;
}
onPageSizeChange(pageSize: number): void {
this.userService.setItemsPerPage(pageSize);
this.searchText = value;
}
nextPage(): void {
this.userService.nextPage();
totalPages(): number {
return Math.ceil(this.allItems.length / this.itemsPerPage);
}
previousPage(): void {
this.userService.previousPage();
if (this.currentPage > 1) {
this.currentPage--;
}
}
nextPage(): void {
if (this.currentPage < this.totalPages()) {
this.currentPage++;
}
}
getTotalPages(): number {
return this.userService.getTotalPages();
itemsPerPageChanged(): void {
this.currentPage = 1;
this.updatePagedItems();
}
onSubmit() {
if (this.userForm.invalid) {
this.userForm.markAllAsTouched();
return;
}
this.userForm.markAllAsTouched();
return;
}
const newUser : SetupUser = {
userId: this.userForm.value.userId,
@ -87,12 +94,11 @@ export class SetupUserComponent implements OnInit {
password: this.userForm.value.defaultPassword
}
this.userService.addUser(newUser).subscribe({
this.httpService.requestPOST<SetupUser[]>(URIKey.CREATE_USER, newUser).subscribe({
next: () => {
this.userService.loadUsers();
this.userService.loadUsers();
this.userForm.reset();
this.mode = 'edit';
this.loadUsersDirect()
},
error: (err: any) => console.error(err)
@ -101,34 +107,20 @@ export class SetupUserComponent implements OnInit {
}
onView(userId: any){
this.mode = 'view';
this.showForm = true;
this.selectedUserId = userId;
this.userService.getUserById(userId).subscribe((user: any)=>{
this.userForm.patchValue({
userId : user.userId,
userFullname : user.userFullname,
defaultPassword : '',
})
})
}
onDelete(userId: any){
this.userService.deleteUser(userId).subscribe({
next: (res: any) => {
this.userService.loadUsers();
this.userForm.reset()
this.selectedUserId = null;
},
error: (err:any) =>{
console.log('user not deleted')
}
});
updatePagedItems(): void {
const startIndex = (this.currentPage - 1) * this.itemsPerPage;
const endIndex = startIndex + this.itemsPerPage;
this.pagedItems = this.allItems.slice(startIndex, endIndex);
}
getButtonPermissions(){
this.buttonPermissions = this.buttonManagementService.buttonPermissions["setupUser"];
}
toggleTableCard(): void {
this.userSetupDataExpanded = !this.userSetupDataExpanded;
}
ngOnInit(): void {
this.getButtonPermissions();
@ -140,25 +132,66 @@ ngOnInit(): void {
email: ['', [Validators.required, Validators.email]],
userRole: [null, Validators.required]
});
this.loadUsersDirect();
}
this.userService.loadUsers();
this.userService.users$.subscribe((users: SetupUser[]) => {
this.allItems = users;
});
this.userService.currentPage$.subscribe((page: number) => {
this.currentPage = page;
});
this.userService.totalCount$.subscribe((count: number) => {
this.totalCount = count;
loadUsersDirect(): void {
this.isLoading = false;
let params = new HttpParams()
.set('page', this.currentPage.toString())
.set('size', this.itemsPerPage.toString());
this.httpService.requestGET<any[]>(URIKey.GET_ALL_USER_URI, params).subscribe({
next: (response) => {
this.setupUserList = response
this.allItems = [...this.setupUserList];
this.updatePagedItems();
this.isLoading = false;
},
error: (err) => {
console.error('Error fetching users:', err);
this.allItems = [];
this.isLoading = false;
}
});
this.userService.itemsPerPage$.subscribe((size: number) => {
this.itemsPerPage = size;
}
onView(userId: any): void{
let params = new HttpParams().set('userId', userId);
this.httpService.requestGET<SetupUser>(URIKey.GET_USER_BY_ID, params).subscribe({
next: (response: SetupUser) => {
this.userForm.patchValue({
userId: response.userId,
userFullname: response.userFullname,
email: response.email,
userRole: response.role,
defaultPassword: ''
});
this.selectedUserId = userId;
this.isLoading = false;
},
error: (err) => {
console.error('Error fetching users:', err);
this.allItems = [];
this.isLoading = false;
}
});
}
}
getButtonPermissions(){
this.buttonPermissions = this.buttonManagementService.buttonPermissions["setupUser"];
onDelete(userId: any){
let params = new HttpParams().set('userId', userId);
this.httpService.requestDELETE<any>(URIKey.DELETE_USER, params).subscribe({
next: (response) =>{
this.loadUsersDirect();
this.userForm.reset()
this.selectedUserId = null;
},
error: (err) =>{
console.error('Error fetching users:', err);
this.allItems = [];
this.isLoading = false;
}
})
}
}

@ -249,6 +249,7 @@
"allow": "يسمح",
"toDateInvalidError": "يجب أن يكون تاريخ اليوم أكبر من أو يساوي تاريخ البداية",
"noLoggingDetailsFound": "لم يتم العثور على تفاصيل التسجيل",
"noUserDetailsFound": "لم يتم العثور على تفاصيل المستخدم",
"ERR_SEC_0001": "البريد الإلكتروني موجود بالفعل",
"ERR_SEC_0002": "اسم المستخدم موجود بالفعل",
"ERR_SEC_0003": "كلمة المرور القديمة غير صحيحة",

@ -249,6 +249,7 @@
"allow": "Allow",
"toDateInvalidError": "To Date must be greater than or equal to From Date",
"noLoggingDetailsFound": "No Logging Details found",
"noUserDetailsFound":"No User Details found",
"ERR_SEC_0001": "Email already exists",
"ERR_SEC_0002": "Username already exists",
"ERR_SEC_0003": "Old Password is not correct",

Loading…
Cancel
Save