diff --git a/src/app/menu/menu.component.html b/src/app/menu/menu.component.html
index acda97c..70442ab 100644
--- a/src/app/menu/menu.component.html
+++ b/src/app/menu/menu.component.html
@@ -45,33 +45,14 @@
-
-
-
- | {{ "one" | translate }} |
- {{ "ACCOUNT_TO_ACCOUNT" | translate }} |
+
+
+ | {{ i + 1 }} |
+ {{ item.name | translate }} |
|
+ [(ngModel)]="item.checked" />
-
- | {{ "two" | translate }} |
- {{ "GL_TO_GL" | translate }} |
- |
-
-
- | {{ "three" | translate }} |
- {{ "ACCOUNT_TO_GL" | translate }} |
-
- |
-
-
- | {{ "four" | translate }} |
- {{ "GL_TO_ACCOUNT" | translate }} |
-
- |
-
-
-
+
diff --git a/src/app/menu/menu.component.ts b/src/app/menu/menu.component.ts
index e9d7dce..c63dc1f 100644
--- a/src/app/menu/menu.component.ts
+++ b/src/app/menu/menu.component.ts
@@ -9,7 +9,7 @@ import { URIKey } from '../utils/uri-enums';
import { HttpErrorResponse, HttpParams } from '@angular/common/http';
import { CommonModule } from '@angular/common';
import { NgSelectModule } from '@ng-select/ng-select';
-import { Observable } from 'rxjs';
+import { filter, Observable, take } from 'rxjs';
import { SuccessMessages } from '../utils/enums';
import { URIService } from '../app.uri';
@@ -24,6 +24,13 @@ export class MenuComponent {
permission: FormGroup;
showPermissions = false;
permissions: PermissionNode[] = [];
+ saving = false;
+ menuItems = [
+ { name: 'accountToAccount', endpoint: URIKey.ACCOUNT_TO_ACCOUNT, checked: true },
+ { name: 'glToGl', endpoint: URIKey.GL_TO_GL, checked: false },
+ { name: 'accountToGl', endpoint: URIKey.ACCOUNT_TO_GL, checked: false },
+ { name: 'glToAccount', endpoint: URIKey.GL_TO_ACCOUNT, checked: false }
+];
constructor(
private credentialService: CredentialService,
@@ -32,15 +39,10 @@ export class MenuComponent {
private i18nService: I18NService,
private uriService: URIService
) {
- this.permission = this.fb.group({
- allocation: [''],
- userCode: [null],
- userRole: [''],
- });
-
- this.defaultPermissions().subscribe((data: PermissionNode[]) => {
- this.permissions = data;
- });
+ this.permission = this.fb.group({ userCode: [null] });
+ this.defaultPermissions().subscribe((data: PermissionNode[]) => {
+ this.permissions = data; // needed for savePermissions
+ });
}
ngOnInit() {
@@ -52,7 +54,6 @@ export class MenuComponent {
getAllUsers() {
this.httpService.requestGET(URIKey.GET_ALL_USER_URI).subscribe((response) => {
- console.log(URIKey.GET_ALL_USER_URI);
if (!(response instanceof HttpErrorResponse)) {
this.users = response.map(item => ({
userName: item.userFullname,
@@ -61,56 +62,116 @@ export class MenuComponent {
}
});
}
-
- onUserChange() {
+// mapEndpointsToPermissions(endpoints: string[]): PermissionNode[] {
+// return [{
+// name: 'menu',
+// checked: false,
+// expanded: false,
+// children: [
+// { name: 'accountToAccount', checked: endpoints.includes(this.uriService.getURIForRequest(URIKey.ACCOUNT_TO_ACCOUNT)), expanded: false },
+// { name: 'glToGl', checked: endpoints.includes(this.uriService.getURIForRequest(URIKey.GL_TO_GL)), expanded: false },
+// { name: 'accountToGl', checked: endpoints.includes(this.uriService.getURIForRequest(URIKey.ACCOUNT_TO_GL)), expanded: false },
+// { name: 'glToAccount', checked: endpoints.includes(this.uriService.getURIForRequest(URIKey.GL_TO_ACCOUNT)), expanded: false }
+// ]
+// }];
+// }
+onUserChange() {
this.showPermissions = true;
- this.defaultPermissions().subscribe((data: PermissionNode[]) => {
- this.permissions = data;
- const params = new HttpParams().set('userId', this.permission.get('userCode')?.value);
- this.httpService.requestGET(URIKey.USER_GET_PERMISSIONS, params).subscribe((response: any) => {
+ const userId = this.permission.get('userCode')?.value;
+ const params = new HttpParams().set('userId', userId);
+
+ this.httpService.requestGET(URIKey.TRANSACTION_PERMISSIONS, params)
+ .subscribe((response: any) => {
if (!(response instanceof HttpErrorResponse)) {
- // Step 4 - reverse map endpoints back to booleans
- const menuNode = this.permissions.find(x => x.name === 'menu');
- if (menuNode && response.transactionEndpoints) {
- menuNode.accountToAccount = response.transactionEndpoints.includes(this.uriService.getURIForRequest(URIKey.ACCOUNT_TO_ACCOUNT));
- menuNode.glToGl = response.transactionEndpoints.includes(this.uriService.getURIForRequest(URIKey.GL_TO_GL));
- menuNode.accountToGl = response.transactionEndpoints.includes(this.uriService.getURIForRequest(URIKey.ACCOUNT_TO_GL));
- menuNode.glToAccount = response.transactionEndpoints.includes(this.uriService.getURIForRequest(URIKey.GL_TO_ACCOUNT));
- }
+
+ const allowedEndpoints: string[] = (response as any[])
+ .filter(p => p.allowed)
+ .map(p => this.normalizeUrl(p.transactionEndpoint)); // ← normalize
+
+ this.uriService.canSubscribe.pipe(
+ filter(ready => ready === true),
+ take(1)
+ ).subscribe(() => {
+ this.menuItems.forEach(item => {
+ const resolvedEndpoint = this.normalizeUrl(
+ this.uriService.getURIForRequest(item.endpoint) // ← normalize
+ );
+ item.checked = allowedEndpoints.includes(resolvedEndpoint);
+ });
+ });
+
+ } else {
+ this.menuItems.forEach(item => item.checked = false);
}
});
- });
}
+// Add this helper method to the class
+private normalizeUrl(url: string): string {
+ return url?.trim().toLowerCase().replace(/\/+$/, ''); // trim, lowercase, remove trailing slash
+}
+
+
+// savePermissions() {
+// const selectedUser = this.permission.get('userCode')?.value;
+// const menuNode = this.permissions.find(x => x.name === 'menu');
+// if (!menuNode) return;
+
+// const nameToURIKey: { [key: string]: URIKey } = {
+// accountToAccount: URIKey.ACCOUNT_TO_ACCOUNT,
+// glToGl: URIKey.GL_TO_GL,
+// accountToGl: URIKey.ACCOUNT_TO_GL,
+// glToAccount: URIKey.GL_TO_ACCOUNT
+// };
+
+// const transactionEndpoints: string[] = (menuNode.children || [])
+// .filter(c => c.checked)
+// .map(c => this.uriService.getURIForRequest(nameToURIKey[c.name]));
+
+// const payload = { userId: selectedUser, transactionEndpoints, permissions: JSON.stringify(this.permissions) };
+
+// this.httpService.requestPOST(URIKey.TRANSACTION_PERMISSIONS_ASSIGN, payload).subscribe((response: any) => {
+// if (!(response instanceof HttpErrorResponse)) {
+// this.i18nService.success(SuccessMessages.SAVED_SUCCESSFULLY, []);
+// this.permission.get('userCode')?.setValue(selectedUser);
+// this.onUserChange();
+// }
+// });
+// }
+
savePermissions() {
- // Step 3 - extract menu node and build endpoints array
- const menuNode = this.permissions.find(x => x.name === 'menu');
- if (!menuNode) return;
-
- const transactionEndpoints: string[] = [];
-
- // Step 2 - map booleans to endpoint strings
- if (menuNode.accountToAccount) transactionEndpoints.push(this.uriService.getURIForRequest(URIKey.ACCOUNT_TO_ACCOUNT));
- if (menuNode.glToGl) transactionEndpoints.push(this.uriService.getURIForRequest(URIKey.GL_TO_GL));
- if (menuNode.accountToGl) transactionEndpoints.push(this.uriService.getURIForRequest(URIKey.ACCOUNT_TO_GL));
- if (menuNode.glToAccount) transactionEndpoints.push(this.uriService.getURIForRequest(URIKey.GL_TO_ACCOUNT));
-
- // Step 1 - new payload structure
- const payload = {
- userId: this.permission.get('userCode')?.value,
- transactionEndpoints
- };
-
- this.httpService.requestPUT(URIKey.TRANSACTION_PERMISSIONS_ASSIGN, payload).subscribe((response: any) => {
- if (!(response instanceof HttpErrorResponse)) {
- this.i18nService.success(SuccessMessages.SAVED_SUCCESSFULLY, []);
- this.permission.get('userCode')?.setValue(null);
- this.showPermissions = false;
- }
- });
+ if (this.saving) return; // ← guard against double clicks
+ this.saving = true;
-}
+ const selectedUser = this.permission.get('userCode')?.value;
+
+ this.uriService.canSubscribe.pipe(
+ filter(ready => ready === true),
+ take(1)
+ ).subscribe(() => {
+ const transactionEndpoints: string[] = this.menuItems
+ .filter(item => item.checked)
+ .map(item => this.uriService.getURIForRequest(item.endpoint));
+
+ const payload = { userId: selectedUser, transactionEndpoints };
+ this.httpService.requestPOST(URIKey.TRANSACTION_PERMISSIONS_ASSIGN, payload)
+ .subscribe({
+ next: (response: any) => {
+ if (!(response instanceof HttpErrorResponse)) {
+ this.i18nService.success(SuccessMessages.SAVED_SUCCESSFULLY, []);
+ this.onUserChange(); // this triggers one GET — expected
+ }
+ },
+ complete: () => {
+ this.saving = false; // ← reset after done
+ },
+ error: () => {
+ this.saving = false;
+ }
+ });
+ });
+}
updatePermissions(savedPermissions: PermissionNode[], existingPermissions: PermissionNode[]): void {
for (const existingNode of existingPermissions) {
const savedNode = savedPermissions.find(node => node.name === existingNode.name);
diff --git a/src/app/utils/uri-enums.ts b/src/app/utils/uri-enums.ts
index f1eb15d..c1e3236 100644
--- a/src/app/utils/uri-enums.ts
+++ b/src/app/utils/uri-enums.ts
@@ -20,6 +20,7 @@ export enum URIKey {
GL_TO_GL = "GL_TO_GL",
ACCOUNT_TO_GL = "ACCOUNT_TO_GL",
GL_TO_ACCOUNT = "GL_TO_ACCOUNT",
- TRANSACTION_PERMISSIONS_ASSIGN = "TRANSACTION_PERMISSIONS_ASSIGN"
+ TRANSACTION_PERMISSIONS_ASSIGN = "TRANSACTION_PERMISSIONS_ASSIGN",
+ TRANSACTION_PERMISSIONS = "TRANSACTION_PERMISSIONS"
}
\ No newline at end of file
diff --git a/src/assets/data/app.uri.json b/src/assets/data/app.uri.json
index 4cd7100..9abba5b 100644
--- a/src/assets/data/app.uri.json
+++ b/src/assets/data/app.uri.json
@@ -111,6 +111,11 @@
"Id": "ENTITY_GL_TO_ACCOUNT",
"URI": "/transactions/gl-account",
"UUID": "GL_TO_ACCOUNT"
+ },
+ {
+ "Id": "ENTITY_TRANSACTION_PERMISSIONS",
+ "URI": "/transaction-permissions/{userId}",
+ "UUID": "TRANSACTION_PERMISSIONS"
}
]
}
diff --git a/src/assets/data/sideMenu.json b/src/assets/data/sideMenu.json
index 7929f92..1e64e9b 100644
--- a/src/assets/data/sideMenu.json
+++ b/src/assets/data/sideMenu.json
@@ -75,10 +75,6 @@
"route": "/home/menu",
"checked": false,
"expanded": false,
- "accountToAccount": false,
- "glToGl": false,
- "accountToGl": false,
- "glToAccount": false,
"children": []
},
{