WEB-398 fix(breadcrumb):update breadcrumb headings on language change (#2954)

This commit is contained in:
Shubham Kumar
2025-12-31 11:07:56 -06:00
committed by GitHub
parent 53a238a1cb
commit e52691bf85
@@ -1,9 +1,10 @@
/** Angular Imports */ /** Angular Imports */
import { Component, TemplateRef, ElementRef, ViewChild, AfterViewInit, inject } from '@angular/core'; import { Component, TemplateRef, ElementRef, ViewChild, AfterViewInit, OnDestroy, inject } from '@angular/core';
import { ActivatedRoute, Router, NavigationEnd, Data, RouterLink } from '@angular/router'; import { ActivatedRoute, Router, NavigationEnd, Data, RouterLink } from '@angular/router';
/** rxjs Imports */ /** rxjs Imports */
import { filter } from 'rxjs/operators'; import { filter, takeUntil } from 'rxjs/operators';
import { merge, Subject } from 'rxjs';
/** Custom Model */ /** Custom Model */
import { Breadcrumb } from './breadcrumb.model'; import { Breadcrumb } from './breadcrumb.model';
@@ -54,12 +55,13 @@ const routeAddBreadcrumbLink = 'addBreadcrumbLink';
...STANDALONE_SHARED_IMPORTS ...STANDALONE_SHARED_IMPORTS
] ]
}) })
export class BreadcrumbComponent implements AfterViewInit { export class BreadcrumbComponent implements AfterViewInit, OnDestroy {
private activatedRoute = inject(ActivatedRoute); private activatedRoute = inject(ActivatedRoute);
private router = inject(Router); private router = inject(Router);
private configurationWizardService = inject(ConfigurationWizardService); private configurationWizardService = inject(ConfigurationWizardService);
private popoverService = inject(PopoverService); private popoverService = inject(PopoverService);
private translateService = inject(TranslateService); private translateService = inject(TranslateService);
private destroy$ = new Subject<void>();
/** Array of breadcrumbs. */ /** Array of breadcrumbs. */
breadcrumbs: Breadcrumb[]; breadcrumbs: Breadcrumb[];
@@ -85,142 +87,130 @@ export class BreadcrumbComponent implements AfterViewInit {
generateBreadcrumbs() { generateBreadcrumbs() {
const onNavigationEnd = this.router.events.pipe(filter((event) => event instanceof NavigationEnd)); const onNavigationEnd = this.router.events.pipe(filter((event) => event instanceof NavigationEnd));
onNavigationEnd.subscribe(() => { // Merge navigation events with language change events to regenerate breadcrumbs when language changes
this.breadcrumbs = []; merge(onNavigationEnd, this.translateService.onLangChange)
let currentRoute = this.activatedRoute.root; .pipe(takeUntil(this.destroy$))
let currentUrl = ''; .subscribe(() => {
this.breadcrumbs = [];
let currentRoute = this.activatedRoute.root;
let currentUrl = '';
while (currentRoute.children.length > 0) { while (currentRoute.children.length > 0) {
const childrenRoutes = currentRoute.children; const childrenRoutes = currentRoute.children;
let breadcrumbLabel: any; let breadcrumbLabel: any;
let url: any; let url: any;
childrenRoutes.forEach((route) => { childrenRoutes.forEach((route) => {
currentRoute = route; currentRoute = route;
breadcrumbLabel = false; breadcrumbLabel = false;
if (route.outlet !== 'primary') { if (route.outlet !== 'primary') {
return; return;
} }
const routeURL = route.snapshot.url.map((segment) => segment.path).join('/'); const routeURL = route.snapshot.url.map((segment) => segment.path).join('/');
currentUrl += `/${routeURL}`; currentUrl += `/${routeURL}`;
if (currentUrl === '/') { if (currentUrl === '/') {
breadcrumbLabel = 'Home'; breadcrumbLabel = 'Home';
} }
const hasData = route.routeConfig && route.routeConfig.data; const hasData = route.routeConfig && route.routeConfig.data;
if (hasData) { if (hasData) {
if (
route.snapshot.data.hasOwnProperty(routeResolveBreadcrumb) &&
route.snapshot.data[routeResolveBreadcrumb]
) {
breadcrumbLabel = route.snapshot.data;
route.snapshot.data[routeResolveBreadcrumb].forEach((property: any) => {
breadcrumbLabel = breadcrumbLabel[property];
});
} else if (
route.snapshot.data.hasOwnProperty(routeParamBreadcrumb) &&
route.snapshot.paramMap.get(route.snapshot.data[routeParamBreadcrumb])
) {
breadcrumbLabel = route.snapshot.paramMap.get(route.snapshot.data[routeParamBreadcrumb]);
const routeData: Data = route.snapshot.data;
if (routeData.breadcrumb === 'Clients') {
breadcrumbLabel = this.printableValue(routeData.clientViewData.displayName);
currentUrl += `/general`;
} else if (routeData.breadcrumb === 'Groups') {
breadcrumbLabel = routeData.groupViewData.name;
} else if (routeData.breadcrumb === 'Centers') {
breadcrumbLabel = routeData.centerViewData.name;
} else if (routeData.breadcrumb === 'Loans') {
breadcrumbLabel =
this.printableValue(routeData.loanDetailsData.loanProductName) +
' (' +
routeData.loanDetailsData.accountNo +
')';
} else if (routeData.breadcrumb === 'Savings') {
const savingsProductName = routeData.savingsAccountData?.savingsProductName ?? '';
const accountNo = routeData.savingsAccountData?.accountNo ?? '';
breadcrumbLabel = this.printableValue(savingsProductName) + (accountNo ? ' (' + accountNo + ')' : '');
} else if (routeData.breadcrumb === 'Fixed Deposits') {
breadcrumbLabel =
this.printableValue(routeData.fixedDepositsAccountData.depositProductName) +
' (' +
routeData.fixedDepositsAccountData.accountNo +
')';
} else if (routeData.breadcrumb === 'Loan Products') {
breadcrumbLabel = this.printableValue(routeData.loanProduct.name);
} else if (routeData.breadcrumb === 'Charges') {
breadcrumbLabel = routeData.loansAccountCharge.name;
} else if (routeData.breadcrumb === 'Saving Products') {
breadcrumbLabel = routeData.savingProduct.name;
} else if (routeData.breadcrumb === 'Share Products') {
breadcrumbLabel = routeData.shareProduct.name;
} else if (routeData.breadcrumb === 'Fixed Deposit Products') {
breadcrumbLabel = routeData.fixedDepositProduct.name;
} else if (routeData.breadcrumb === 'Recurring Deposit Products') {
breadcrumbLabel = routeData.recurringDepositProduct.name;
} else if (routeData.breadcrumb === 'Floating Rates') {
breadcrumbLabel = routeData.floatingRate.name;
} else if (routeData.breadcrumb === 'Tax Components') {
breadcrumbLabel = routeData.taxComponent.name;
} else if (routeData.breadcrumb === 'Tax Groups') {
breadcrumbLabel = routeData.taxGroup.name;
}
// Check if the breadcrumbLabel is an action name that should be translated using labels.menus
// This handles action names from route parameters for Savings, Loans, Shares, Fixed Deposits, and Recurring Deposits accounts
if ( if (
breadcrumbLabel && route.snapshot.data.hasOwnProperty(routeResolveBreadcrumb) &&
(routeData.breadcrumb === 'Savings Account Actions' || route.snapshot.data[routeResolveBreadcrumb]
routeData.breadcrumb === 'Loan Account Actions' ||
routeData.breadcrumb === 'Shares Account Actions' ||
routeData.breadcrumb === 'Actions' ||
routeData.breadcrumb === 'action' ||
routeData.title === 'Fixed Deposits Account Actions' ||
routeData.title === 'Recurring Deposits Account Actions')
) { ) {
const menuKey = 'labels.menus.' + breadcrumbLabel; breadcrumbLabel = route.snapshot.data;
const menuTranslation = this.translateService.instant(menuKey); route.snapshot.data[routeResolveBreadcrumb].forEach((property: any) => {
if (menuTranslation !== menuKey) { breadcrumbLabel = breadcrumbLabel[property];
breadcrumbLabel = menuTranslation; });
} else if (
route.snapshot.data.hasOwnProperty(routeParamBreadcrumb) &&
route.snapshot.paramMap.get(route.snapshot.data[routeParamBreadcrumb])
) {
breadcrumbLabel = route.snapshot.paramMap.get(route.snapshot.data[routeParamBreadcrumb]);
const routeData: Data = route.snapshot.data;
if (routeData.breadcrumb === 'Clients') {
breadcrumbLabel = this.printableValue(routeData.clientViewData.displayName);
currentUrl += `/general`;
} else if (routeData.breadcrumb === 'Groups') {
breadcrumbLabel = routeData.groupViewData.name;
} else if (routeData.breadcrumb === 'Centers') {
breadcrumbLabel = routeData.centerViewData.name;
} else if (routeData.breadcrumb === 'Loans') {
breadcrumbLabel =
this.printableValue(routeData.loanDetailsData.loanProductName) +
' (' +
routeData.loanDetailsData.accountNo +
')';
} else if (routeData.breadcrumb === 'Savings') {
const savingsProductName = routeData.savingsAccountData?.savingsProductName ?? '';
const accountNo = routeData.savingsAccountData?.accountNo ?? '';
breadcrumbLabel = this.printableValue(savingsProductName) + (accountNo ? ' (' + accountNo + ')' : '');
} else if (routeData.breadcrumb === 'Fixed Deposits') {
breadcrumbLabel =
this.printableValue(routeData.fixedDepositsAccountData.depositProductName) +
' (' +
routeData.fixedDepositsAccountData.accountNo +
')';
} else if (routeData.breadcrumb === 'Loan Products') {
breadcrumbLabel = this.printableValue(routeData.loanProduct.name);
} else if (routeData.breadcrumb === 'Charges') {
breadcrumbLabel = routeData.loansAccountCharge.name;
} else if (routeData.breadcrumb === 'Saving Products') {
breadcrumbLabel = routeData.savingProduct.name;
} else if (routeData.breadcrumb === 'Share Products') {
breadcrumbLabel = routeData.shareProduct.name;
} else if (routeData.breadcrumb === 'Fixed Deposit Products') {
breadcrumbLabel = routeData.fixedDepositProduct.name;
} else if (routeData.breadcrumb === 'Recurring Deposit Products') {
breadcrumbLabel = routeData.recurringDepositProduct.name;
} else if (routeData.breadcrumb === 'Floating Rates') {
breadcrumbLabel = routeData.floatingRate.name;
} else if (routeData.breadcrumb === 'Tax Components') {
breadcrumbLabel = routeData.taxComponent.name;
} else if (routeData.breadcrumb === 'Tax Groups') {
breadcrumbLabel = routeData.taxGroup.name;
} }
// For action names, keep the original name and let getTranslate() handle translation dynamically
// This ensures breadcrumbs update when language changes without requiring navigation
// The getTranslate() method will check both labels.text.* and labels.menus.* for translations
} else if (route.snapshot.data.hasOwnProperty(routeDataBreadcrumb)) {
breadcrumbLabel = route.snapshot.data[routeDataBreadcrumb];
}
if (route.snapshot.data.hasOwnProperty(routeAddBreadcrumbLink)) {
url = route.snapshot.data[routeAddBreadcrumbLink];
} else {
url = currentUrl;
}
}
if (url !== undefined) {
if (url.length > 8 && url.search(`/clients/`) > 0) {
const replaceGeneral = `/general/`;
let currentUrlTemp = url.replace(replaceGeneral, `/`);
currentUrlTemp = currentUrlTemp.replace(`//`, `/`);
currentUrlTemp += `/general`;
const replaceDoubleSlash = `/general/general`;
currentUrlTemp = currentUrlTemp.replace(replaceDoubleSlash, `/general`);
url = currentUrlTemp;
} }
} else if (route.snapshot.data.hasOwnProperty(routeDataBreadcrumb)) {
breadcrumbLabel = route.snapshot.data[routeDataBreadcrumb];
} }
if (route.snapshot.data.hasOwnProperty(routeAddBreadcrumbLink)) { const breadcrumb: Breadcrumb = {
url = route.snapshot.data[routeAddBreadcrumbLink]; label: breadcrumbLabel,
} else { url: url
url = currentUrl; };
}
}
if (url !== undefined) {
if (url.length > 8 && url.search(`/clients/`) > 0) {
const replaceGeneral = `/general/`;
let currentUrlTemp = url.replace(replaceGeneral, `/`);
currentUrlTemp = currentUrlTemp.replace(`//`, `/`);
currentUrlTemp += `/general`;
const replaceDoubleSlash = `/general/general`;
currentUrlTemp = currentUrlTemp.replace(replaceDoubleSlash, `/general`);
url = currentUrlTemp;
}
}
const breadcrumb: Breadcrumb = { if (breadcrumbLabel) {
label: breadcrumbLabel, this.breadcrumbs.push(breadcrumb);
url: url }
}; });
}
if (breadcrumbLabel) { });
this.breadcrumbs.push(breadcrumb);
}
});
}
});
} }
printableValue(value: string): string { printableValue(value: string): string {
@@ -280,9 +270,29 @@ export class BreadcrumbComponent implements AfterViewInit {
} }
getTranslate(text: string): any { getTranslate(text: string): any {
const key: string = 'labels.text.' + text; // First try labels.text.* (for static breadcrumb labels)
const translation = this.translateService.instant(key); let key: string = 'labels.text.' + text;
const result = translation !== key ? translation : text; let translation = this.translateService.instant(key);
return result; if (translation !== key) {
return translation;
}
// Then try labels.menus.* (for action names like "View Guarantors")
key = 'labels.menus.' + text;
translation = this.translateService.instant(key);
if (translation !== key) {
return translation;
}
// If no translation found, return the original text
return text;
}
/**
* Clean up subscriptions on component destroy.
*/
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
} }
} }