Merge pull request 'aconnect-UX/1653' (#14) from aconnect-UX/1653 into dev-pending-09-12-2025

Reviewed-on: https://ct.mfsys.com.pk/aConnect/aConnect-UX/pulls/14
dev-pending-09-12-2025
Naeem Ullah 6 hours ago
commit c93f231dfd

@ -46,7 +46,7 @@ passwordType2: string = 'password';
checkIfFirstTimeChangePasswordOrNot(){
let currentUser: any = JSON.parse(this.storageService.getItem('user')!)
if(currentUser.user.isFirstLogin){
if(currentUser?.user?.isFirstLogin){
this.isFirstLogin = true;
}
else{

@ -1 +1,95 @@
<p>user-permissions works!</p>
<div class="page-content">
<div class="container-fluid">
<div class="row mt-2 mb-2">
<div class="col-lg-6">
<div class="col-6">
<div class="mt-0 mb-2 d-sm-flex align-items-center justify-content-between font-edit-13">
<h5 class="text-muted fw-bold mt-3">{{'permissionManagement' | translate}}</h5>
</div>
</div>
<div class="card">
<div class="card-body">
<form [formGroup]="permission">
<div class="form-group row mb-2">
<label for="userCode" class="form-label font-edit-13">{{ 'userCode' |
translate
}}</label>
<div class="input-group">
<select class="form-select" id="userCode" formControlName="userCode" (change)="onUserChange()">
<option selected disabled value="">{{ 'choose' |
translate }}
</option>
<option *ngFor="let user of users" [value]="user.userId">
{{user.userName}}
</option>
</select>
</div>
</div>
</form>
</div>
</div>
<div class="card" *ngIf="showPermissions">
<div class="card-body">
<h4 class="card-title">{{ 'permissions' | translate}}</h4>
<hr>
<ul>
<li *ngFor="let node of permissions">
<input
type="checkbox"
[checked]="node.checked"
(change)="toggleNode(node, $event)">
{{node.name | translate}}
<span (click)="toggleExpand(node)">
<span *ngIf="node.children && node.children.length">
<span *ngIf="node.expanded"><i class="bx bx-chevron-down"></i></span>
<span *ngIf="!node.expanded"><i class="bx bx-chevron-right"></i></span>
</span>
</span>
<ul *ngIf="node.children && node.children.length > 0 && node.expanded">
<ng-container *ngTemplateOutlet="treeTemplate; context: { $implicit: node.children }"></ng-container>
</ul>
<ul *ngIf="node.buttons && node.buttons.length > 0 && node.expanded">
<ng-container *ngTemplateOutlet="treeTemplate; context: { $implicit: node.buttons }"></ng-container>
</ul>
</li>
</ul>
<ng-template #treeTemplate let-nodes>
<ul>
<li *ngFor="let node of nodes">
<input
type="checkbox"
[checked]="node.checked"
(change)="toggleNode(node, $event)">
{{node.name | translate}}
<span (click)="toggleExpand(node)">
<span *ngIf="node.children && node.children.length">
<span *ngIf="node.expanded"><i class="bx bx-chevron-down"></i></span>
<span *ngIf="!node.expanded"><i class="bx bx-chevron-right"></i></span>
</span>
<span *ngIf="node.buttons && node.buttons.length">
<span *ngIf="node.expanded"><i class="bx bx-chevron-down"></i></span>
<span *ngIf="!node.expanded"><i class="bx bx-chevron-right"></i></span>
</span>
</span>
<ul *ngIf="node.children && node.children.length > 0 && node.expanded">
<ng-container *ngTemplateOutlet="treeTemplate; context: { $implicit: node.children }"></ng-container>
</ul>
<ul *ngIf="node.buttons && node.buttons.length > 0 && node.expanded">
<ng-container *ngTemplateOutlet="treeTemplate; context: { $implicit: node.buttons }"></ng-container>
</ul>
</li>
</ul>
</ng-template>
<div class="row float-end me-4 mb-3 mt-2 font-edit-13">
<button type="button" class="btn btn-primary font-edit-13 px-3 btn-sm" (click)="savePermissions()">{{ 'save' | translate }}</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

@ -0,0 +1,19 @@
li {
margin: 5px 0;
}
ul {
list-style-type: none;
margin: 0;
padding-left: 10px; /* Reduce overall left padding */
}
ul ul {
padding-left: 5px; /* Reduce space for nested items */
margin-left: 5px;
}
li {
margin-bottom: 3px; /* Add slight vertical spacing between items */
}

@ -1,11 +1,180 @@
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { PermissionNode } from '../utils/app.constants';
import { Observable } from 'rxjs';
import { CredentialService } from '../services/credential.service';
import { I18NService } from '../services/i18n.service';
import { HttpURIService } from '../app.http.uri.service';
import { TranslateModule } from '@ngx-translate/core';
import { URIKey } from '../utils/uri-enums';
import { HttpErrorResponse, HttpParams } from '@angular/common/http';
import { FormConstants, HiddenValues, SuccessMessages } from '../utils/enums';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-user-permissions',
imports: [],
imports: [TranslateModule, ReactiveFormsModule, CommonModule],
templateUrl: './user-permissions.component.html',
styleUrl: './user-permissions.component.scss'
})
export class UserPermissionsComponent {
dropdownOptions: { [key: string]: any[] } = {};
users: any[] = [];
permission: FormGroup;
showPermissions = false;
permissions: PermissionNode[] = [];
constructor(private credentialService: CredentialService, private fb: FormBuilder, private httpService: HttpURIService, private i18nService: I18NService) {
this.permission = this.fb.group({
allocation: [''],
userCode: [''],
userRole: [''],
});
this.defaultPermissions().subscribe((data: PermissionNode[]) => {
this.permissions = data;
});
this.getAllUsers(HiddenValues.VAC_USER);
}
defaultPermissions(): Observable<PermissionNode[]> {
return this.httpService.requestGET<PermissionNode[]>('assets/data/sideMenu.json');
}
toggleNode(node: PermissionNode, event: Event): void {
node.checked = (event.target as HTMLInputElement).checked;
if (node.children) {
this.toggleChildren(node.children, node.checked);
}
if (node.buttons) {
this.toggleButtons(node.buttons, node.checked);
}
this.updateParentState(node);
}
toggleChildren(children: PermissionNode[], isChecked: boolean): void {
children.forEach(child => {
child.checked = isChecked;
if (child.children) {
this.toggleChildren(child.children, isChecked);
}
if (child.buttons) {
this.toggleButtons(child.buttons, child.checked);
}
});
}
toggleButtons(buttons: PermissionNode[], isChecked: boolean): void {
buttons.forEach(button => {
button.checked = isChecked;
});
}
updateParentState(node: PermissionNode): void {
const parent = this.findParent(node, this.permissions);
if (parent) {
parent.checked = parent.children?.some(child => child.checked) || false;
this.updateParentState(parent); // Recursively update ancestors
}
}
findParent(target: PermissionNode, nodes: PermissionNode[]): PermissionNode | null {
for (let node of nodes) {
if (node.children?.includes(target)) {
return node;
}
if (node.children) {
const parent = this.findParent(target, node.children);
if (parent) return parent;
}
}
return null;
}
toggleExpand(node: PermissionNode): void {
node.expanded = !node.expanded;
}
populateDropdowns(data: any) {
data.forEach((control: any) => {
this.dropdownOptions[control.controlId] = control.options;
});
}
onAllocationChange(event: Event): void {
this.showPermissions = false;
const selectedValue = (event.target as HTMLInputElement).value;
if (selectedValue === "R") {
this.permission.get('userCode')?.reset();
}
else if (selectedValue === "U") {
this.permission.get('userRole')?.reset();
}
}
getAllUsers(userType: string) {
let porOrgacode = this.credentialService.getPorOrgacode();
const params = new HttpParams().set('porOrgacode', porOrgacode)
.append('userType', userType);
// this.httpService.requestGET<any[]>(URIKey.GET_ALL_USER_URI, params).subscribe((response) => {
// if (!(response instanceof HttpErrorResponse)) {
// this.users = response.map(item => ({
// userName: item.userName,
// userId: item.userId,
// }));
// }
// });
}
onUserChange() {
this.showPermissions = true;
const params = new HttpParams().set(FormConstants.POR_ORGACODE, this.credentialService.getPorOrgacode())
.append(FormConstants.USER_ID, this.permission.get('userCode')?.value);
// this.httpService.requestGET(URIKey.USER_GET_PERMISSIONS, params).subscribe((response: any) => {
// if (!(response instanceof HttpErrorResponse)) {
// if (response.permission) {
// this.updatePermissions(JSON.parse(response.permission), this.permissions);
// }
// else {
// this.defaultPermissions().subscribe((data: PermissionNode[]) => {
// this.permissions = data;
// });
// }
// }
// })
}
savePermissions() {
let payload = {
porOrgacode: this.credentialService.getPorOrgacode(),
userId: this.permission.get('userCode')?.value,
permission: JSON.stringify(this.permissions)
}
// this.httpService.requestPATCH(URIKey.USER_SAVE_PERMISSION, payload).subscribe((response: any) => {
// if (!(response instanceof HttpErrorResponse)) {
// this.i18nService.success(SuccessMessages.SAVED_SUCESSFULLY, []);
// this.permission.reset();
// this.showPermissions = false;
// }
// })
}
updatePermissions(savedPermissions: PermissionNode[], existingPermissions: PermissionNode[]): void {
for (const existingNode of existingPermissions) {
const savedNode = savedPermissions.find(node => node.name === existingNode.name);
if (savedNode) {
// Update state from saved node
existingNode.checked = savedNode.checked;
//existingNode.expanded = savedNode.expanded;
// Recursively update children if they exist
if (existingNode.children) {
this.updatePermissions(savedNode.children || [], existingNode.children);
}
if (existingNode.buttons) {
this.updatePermissions(savedNode.buttons || [], existingNode.buttons);
}
}
}
}
}

@ -1,5 +1,8 @@
export enum URIKey {
USER_LOGIN_URI = "USER_LOGIN_URI",
USER_REFRESH_TOKEN = "USER_REFRESH_TOKEN"
USER_REFRESH_TOKEN = "USER_REFRESH_TOKEN",
USER_SAVE_PERMISSION = "USER_SAVE_PERMISSION",
USER_GET_PERMISSIONS = "USER_GET_PERMISSIONS",
GET_ALL_USER_URI = "GET_ALL_USER_URI"
}

@ -210,21 +210,7 @@
"route": "/home/permissions",
"checked": false,
"expanded": false,
"children": [],
"buttons": [
{
"name": "edit",
"route": "",
"checked": false,
"expanded": false
},
{
"name": "delete",
"route": "",
"checked": false,
"expanded": false
}
]
"children": []
}
]
}

@ -220,5 +220,10 @@
"CONNECTION_ERROR": "خطأ في الاتصال",
"BAD_REQUEST": "اقتراح غير جيد",
"FORBIDDEN_REQUEST": "طلب ممنوع",
"UNAUTHORIZED_REQUEST": "طلب غير مصرح به"
"UNAUTHORIZED_REQUEST": "طلب غير مصرح به",
"edit": "يحرر",
"delete": "يمسح",
"permissionManagement": "إدارة الأذونات",
"userCode": "مستخدم",
"choose" : "يختار"
}

@ -219,5 +219,10 @@
"CONNECTION_ERROR": "Connection Error",
"BAD_REQUEST": "Bad Request",
"FORBIDDEN_REQUEST": "Forbidden Request",
"UNAUTHORIZED_REQUEST": "Unauthorized Request"
"UNAUTHORIZED_REQUEST": "Unauthorized Request",
"edit": "Edit",
"delete": "Delete",
"permissionManagement": "Permission Managment",
"userCode": "User",
"choose" : "Choose"
}
Loading…
Cancel
Save