diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index ef5249d..2a66d09 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -139,7 +139,16 @@ export const routes: Routes = [ import('./user-management/change-password/change-password.component').then( m => m.ChangePasswordComponent ) - } + }, + { + path: 'menu', + canActivate: [ActivityGuard], + loadComponent: () => + import('./menu/menu.component').then( + m => m.MenuComponent + ) + }, + ] }, { diff --git a/src/app/menu/menu.component.html b/src/app/menu/menu.component.html new file mode 100644 index 0000000..acda97c --- /dev/null +++ b/src/app/menu/menu.component.html @@ -0,0 +1,86 @@ +
+
+ +
+
+
+ +
+ + + +
+ {{ item.userName }} + {{ item.userId }} +
+
+ + + + {{ item.userName }} ({{ item.userId }}) + +
+
+
+
+
+ +
+
+

{{ "menu" | translate }}

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#{{ "type" | translate }}{{ "allow" | translate }}
{{ "one" | translate }}{{ "ACCOUNT_TO_ACCOUNT" | translate }}
{{ "two" | translate }}{{ "GL_TO_GL" | translate }}
{{ "three" | translate }}{{ "ACCOUNT_TO_GL" | translate }} +
{{ "four" | translate }}{{ "GL_TO_ACCOUNT" | translate }} +
+
+ +
+ +
+
+
+
\ No newline at end of file diff --git a/src/app/menu/menu.component.scss b/src/app/menu/menu.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/menu/menu.component.spec.ts b/src/app/menu/menu.component.spec.ts new file mode 100644 index 0000000..7419205 --- /dev/null +++ b/src/app/menu/menu.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MenuComponent } from './menu.component'; + +describe('MenuComponent', () => { + let component: MenuComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MenuComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(MenuComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/menu/menu.component.ts b/src/app/menu/menu.component.ts new file mode 100644 index 0000000..e9d7dce --- /dev/null +++ b/src/app/menu/menu.component.ts @@ -0,0 +1,133 @@ +import { Component } from '@angular/core'; +import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { PermissionNode } from '../utils/app.interfaces'; +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 { CommonModule } from '@angular/common'; +import { NgSelectModule } from '@ng-select/ng-select'; +import { Observable } from 'rxjs'; +import { SuccessMessages } from '../utils/enums'; +import { URIService } from '../app.uri'; + +@Component({ + selector: 'app-menu', + imports: [TranslateModule, ReactiveFormsModule, CommonModule, TranslateModule, NgSelectModule, FormsModule], + templateUrl: './menu.component.html', + styleUrl: './menu.component.scss' +}) +export class MenuComponent { + users: any[] = []; + permission: FormGroup; + showPermissions = false; + permissions: PermissionNode[] = []; + + constructor( + private credentialService: CredentialService, + private fb: FormBuilder, + private httpService: HttpURIService, + private i18nService: I18NService, + private uriService: URIService + ) { + this.permission = this.fb.group({ + allocation: [''], + userCode: [null], + userRole: [''], + }); + + this.defaultPermissions().subscribe((data: PermissionNode[]) => { + this.permissions = data; + }); + } + + ngOnInit() { + this.getAllUsers(); + } + defaultPermissions(): Observable { + return this.httpService.requestGET('assets/data/sideMenu.json'); + } + + 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, + userId: item.userId, + })); + } + }); + } + + 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) => { + 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)); + } + } + }); + }); +} + +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; + } + }); + +} + + 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); + } + } + } + } +} \ No newline at end of file diff --git a/src/app/shared/components/side-nav/side-nav.component.html b/src/app/shared/components/side-nav/side-nav.component.html index 5e7b2e9..c617868 100644 --- a/src/app/shared/components/side-nav/side-nav.component.html +++ b/src/app/shared/components/side-nav/side-nav.component.html @@ -96,6 +96,12 @@ --> +
  • + + + {{ 'menu' | translate }} + +
  • diff --git a/src/app/user-management/reset-password/reset-password.component.ts b/src/app/user-management/reset-password/reset-password.component.ts index 3f1fcef..e386fea 100644 --- a/src/app/user-management/reset-password/reset-password.component.ts +++ b/src/app/user-management/reset-password/reset-password.component.ts @@ -169,6 +169,7 @@ export class ResetPasswordComponent implements OnInit{ .set('size', '1000'); this.httpService.requestGET(URIKey.GET_ALL_USER_URI, params).subscribe({ + next: (response) => { this.allUsersDropdown = response || []; this.isLoading = false; diff --git a/src/app/utils/app.interfaces.ts b/src/app/utils/app.interfaces.ts index 82d3eff..0ba657c 100644 --- a/src/app/utils/app.interfaces.ts +++ b/src/app/utils/app.interfaces.ts @@ -4,6 +4,10 @@ export interface PermissionNode { expanded: boolean; children?: PermissionNode[]; buttons?: PermissionNode[]; + accountToAccount?: boolean; + glToGl?: boolean; + accountToGl?: boolean; + glToAccount?: boolean; } export interface LogsManagementResponse { diff --git a/src/app/utils/uri-enums.ts b/src/app/utils/uri-enums.ts index 9842569..f1eb15d 100644 --- a/src/app/utils/uri-enums.ts +++ b/src/app/utils/uri-enums.ts @@ -15,5 +15,11 @@ export enum URIKey { THIRD_PARTY_REGISTER_URI = "THIRD_PARTY_REGISTER_URI", TRANSACTION_LOGS = "TRANSACTION_LOGS", LOGGER_MANAGER_URI = "LOGGER_MANAGER_URI", - UPDATE_USER = 'UPDATE_USER' + UPDATE_USER = 'UPDATE_USER', + ACCOUNT_TO_ACCOUNT = "ACCOUNT_TO_ACCOUNT", + GL_TO_GL = "GL_TO_GL", + ACCOUNT_TO_GL = "ACCOUNT_TO_GL", + GL_TO_ACCOUNT = "GL_TO_ACCOUNT", + TRANSACTION_PERMISSIONS_ASSIGN = "TRANSACTION_PERMISSIONS_ASSIGN" + } \ No newline at end of file diff --git a/src/assets/data/app.uri.json b/src/assets/data/app.uri.json index 4a0ad4e..4cd7100 100644 --- a/src/assets/data/app.uri.json +++ b/src/assets/data/app.uri.json @@ -86,6 +86,31 @@ "Id": "ENTITY_LOGGER_MANAGER_URI", "URI": "/logs/getByDate", "UUID": "LOGGER_MANAGER_URI" + }, + { + "Id": "ENTITY_TRANSACTION_PERMISSIONS_ASSIGN", + "URI": "/transaction-permissions/assign", + "UUID": "TRANSACTION_PERMISSIONS_ASSIGN" + }, + { + "Id": "ENTITY_ACCOUNT_TO_ACCOUNT", + "URI": "/transactions/accounttoaccount", + "UUID": "ACCOUNT_TO_ACCOUNT" + }, + { + "Id": "ENTITY_GL_TO_GL", + "URI": "/transactions/gltogls", + "UUID": "GL_TO_GL" + }, + { + "Id": "ENTITY_ACCOUNT_TO_GL", + "URI": "/transactions/accounttogl", + "UUID": "ACCOUNT_TO_GL" + }, + { + "Id": "ENTITY_GL_TO_ACCOUNT", + "URI": "/transactions/gl-account", + "UUID": "GL_TO_ACCOUNT" } ] } diff --git a/src/assets/data/sideMenu.json b/src/assets/data/sideMenu.json index beaed46..7929f92 100644 --- a/src/assets/data/sideMenu.json +++ b/src/assets/data/sideMenu.json @@ -70,6 +70,17 @@ } ] }, +{ + "name": "menu", + "route": "/home/menu", + "checked": false, + "expanded": false, + "accountToAccount": false, + "glToGl": false, + "accountToGl": false, + "glToAccount": false, + "children": [] +}, { "name": "permissions", "route": "/home/permissions", diff --git a/src/assets/i18n/Arabic.json b/src/assets/i18n/Arabic.json index 27726a9..2a4c5a2 100644 --- a/src/assets/i18n/Arabic.json +++ b/src/assets/i18n/Arabic.json @@ -313,5 +313,31 @@ "dateRangeError": "الرجاء تحديد نطاق تاريخ صالح", "exportAllData": "تصدير جميع البيانات", "transactionLogDetails": "تفاصيل سجلات المعاملات", - "USER_UPDATED_SUCCESS": "تم تحديث المستخدم بنجاح" + "USER_UPDATED_SUCCESS": "تم تحديث المستخدم بنجاح", + "menu": "القائمة", + "type": "نوع المعاملة", + "ACCOUNT_TO_ACCOUNT": "من حساب إلى حساب", + "GL_TO_GL": "من دفتر الأستاذ إلى دفتر الأستاذ", + "ACCOUNT_TO_GL": "من حساب إلى دفتر الأستاذ", + "GL_TO_ACCOUNT": "من دفتر الأستاذ إلى حساب", + "one": "١", + "two": "٢", + "three": "٣", + "four": "٤", + "five": "٥", + "six": "٦", + "seven": "٧", + "eight": "٨", + "nine": "٩", + "ten": "١٠", + "eleven": "١١", + "twelve": "١٢", + "thirteen": "١٣", + "fourteen": "١٤", + "fifteen": "١٥", + "sixteen": "١٦", + "seventeen": "١٧", + "eighteen": "١٨", + "nineteen": "١٩", + "twenty": "٢٠" } diff --git a/src/assets/i18n/English.json b/src/assets/i18n/English.json index d642fc2..ea1973a 100644 --- a/src/assets/i18n/English.json +++ b/src/assets/i18n/English.json @@ -314,6 +314,31 @@ "dateRangeError": "Please select a valid date range", "exportAllData": "Export All Data", "transactionLogDetails": "Transaction Logs Details", - "USER_UPDATED_SUCCESS": "User Updated Successfully" - + "USER_UPDATED_SUCCESS": "User Updated Successfully", + "menu": "Menu", + "type": "Transaction Type", + "ACCOUNT_TO_ACCOUNT": "Account to Account", + "GL_TO_GL": "General Ledger to General Ledger", + "ACCOUNT_TO_GL": "Account to General Ledger", + "GL_TO_ACCOUNT": "General Ledger to Account", + "one": "1", + "two": "2", + "three": "3", + "four": "4", + "five": "5", + "six": "6", + "seven": "7", + "eight": "8", + "nine": "9", + "ten": "10", + "eleven": "11", + "twelve": "12", + "thirteen": "13", + "fourteen": "14", + "fifteen": "15", + "sixteen": "16", + "seventeen": "17", + "eighteen": "18", + "nineteen": "19", + "twenty": "20" } diff --git a/tsconfig.json b/tsconfig.json index 5525117..2f1a8d6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,6 +3,7 @@ { "compileOnSave": false, "compilerOptions": { + "rootDir": "./src", "outDir": "./dist/out-tsc", "strict": true, "noImplicitOverride": true,