WEB-457 Tenant aware feature (#2854)

* refactor: use inject() for DI in HomeComponent (eslint fix)

* Tenant Fix

* fix: JSON syntax in translation file
This commit is contained in:
Soni Jay
2025-12-17 10:53:45 -06:00
committed by GitHub
parent 4220abcb56
commit 79d0608491
18 changed files with 95 additions and 41 deletions
+5 -2
View File
@@ -10,7 +10,10 @@
<div class="container">
<mat-card>
<mat-card-header>
<mat-card-title class="title"> {{ 'labels.text.Welcome' | translate }}, {{ username }}! </mat-card-title>
<mat-card-title class="title">
{{ 'labels.text.Welcome' | translate }} {{ username }} {{ 'labels.text.To' | translate }}
{{ tenant | titlecase }}!
</mat-card-title>
</mat-card-header>
<mat-card-content #searchActivity>
@@ -30,7 +33,7 @@
</mat-autocomplete>
</mat-card-content>
<img mat-card-image src="assets/images/mifos_lg-logo.png" alt="Mifos X" />
<img mat-card-image src="assets/images/{{ tenant }}_home.png" alt="Mifos X" />
</mat-card>
</div>
+15
View File
@@ -16,6 +16,7 @@ import { WarningDialogComponent } from './warning-dialog/warning-dialog.componen
import { AuthenticationService } from '../core/authentication/authentication.service';
import { PopoverService } from '../configuration-wizard/popover/popover.service';
import { ConfigurationWizardService } from '../configuration-wizard/configuration-wizard.service';
import { SettingsService } from 'app/settings/settings.service';
/** Custom Components */
import { NextStepDialogComponent } from '../configuration-wizard/next-step-dialog/next-step-dialog.component';
@@ -50,9 +51,12 @@ export class HomeComponent implements OnInit, AfterViewInit {
private dialog = inject(MatDialog);
private configurationWizardService = inject(ConfigurationWizardService);
private popoverService = inject(PopoverService);
private settingsService = inject(SettingsService);
/** Username of authenticated user. */
username: string;
/** Tenant name */
tenant: string;
/** Activity Form. */
activityForm: any;
/** Search Text. */
@@ -71,6 +75,9 @@ export class HomeComponent implements OnInit, AfterViewInit {
/* Template for popover on search activity */
@ViewChild('templateSearchActivity', { static: false }) templateSearchActivity: TemplateRef<any>;
// All dependencies are injected using inject() above. No constructor needed.
constructor() {}
/**
* Sets the username of the authenticated user.
* Set Form.
@@ -78,6 +85,7 @@ export class HomeComponent implements OnInit, AfterViewInit {
ngOnInit() {
const credentials = this.authenticationService.getCredentials();
this.username = credentials.username;
this.tenant = this.tenantIdentifier();
this.setFilteredActivities();
if (!this.authenticationService.hasDialogBeenShown()) {
this.dialog.open(WarningDialogComponent);
@@ -183,4 +191,11 @@ export class HomeComponent implements OnInit, AfterViewInit {
this.router.onSameUrlNavigation = 'reload';
this.router.navigate(['/home']);
}
tenantIdentifier() {
if (!this.settingsService.tenantIdentifier || this.settingsService.tenantIdentifier === '') {
return 'default';
}
return this.settingsService.tenantIdentifier;
}
}
+39 -39
View File
@@ -1,41 +1,41 @@
@if (displayBackEndInfo) {
<div class="layout-column m-b-20 f12" ngClass="{{ styleClass }}" id="footer">
<mat-divider class="divider align-center"></mat-divider>
<div class="layout-column m-b-20 content-wrapper footer-center">
<table class="versions">
<tr>
<td class="footer-content">Mifos</td>
<td class="right footer-content">
{{ versions.mifos }} - <b>{{ hash }}</b>
</td>
</tr>
<tr>
<td class="footer-content">{{ 'labels.text.Fineract' | translate }}</td>
<td class="right footer-content">
{{ versions.fineract.version }} - <b>{{ versions.fineract.hash }}</b>
</td>
</tr>
@if (displayBackEndInfo) {
<tr>
<td class="footer-content">{{ 'labels.inputs.Server' | translate }}</td>
<td class="right footer-content">
{{ server }}
</td>
</tr>
}
@if (isBusinessDateDefined) {
<tr>
<td class="footer-content">{{ 'labels.text.Current Business Date' | translate }}:</td>
<td class="center footer-content business-date">
<b>{{ businessDate | date: 'EEEE, MMMM dd, y' }}</b>
</td>
</tr>
}
</table>
</div>
<mat-divider class="divider align-center"></mat-divider>
<div class="layout-column m-b-20 f12" ngClass="{{ styleClass }}" id="footer" *ngIf="displayBackEndInfo">
<mat-divider class="divider align-center"></mat-divider>
<div class="layout-column m-b-20 content-wrapper footer-center">
<table class="versions">
<tr>
<td class="footer-content">Tenant</td>
<td class="right footer-content">
{{ tenant | titlecase }}
</td>
</tr>
<tr>
<td class="footer-content">Mifos</td>
<td class="right footer-content">
{{ versions.mifos }} - <b>{{ hash }}</b>
</td>
</tr>
<tr>
<td class="footer-content">{{ 'labels.text.Fineract' | translate }}</td>
<td class="right footer-content">
{{ versions.fineract.version }} - <b>{{ versions.fineract.hash }}</b>
</td>
</tr>
<tr *ngIf="displayBackEndInfo">
<td class="footer-content">{{ 'labels.inputs.Server' | translate }}</td>
<td class="right footer-content">
{{ server }}
</td>
</tr>
<tr *ngIf="isBusinessDateDefined">
<td class="footer-content">{{ 'labels.text.Current Business Date' | translate }}:</td>
<td class="center footer-content business-date">
<b>{{ businessDate | date: 'EEEE, MMMM dd, y' }}</b>
</td>
</tr>
</table>
</div>
<div class="layout-column m-b-20 copy-label">
<p class="footer-content align-center">{{ 'APP_NAME' | translate }} {{ 'labels.text.by' | translate }} Mifos</p>
</div>
}
<div class="layout-column m-b-20 copy-label">
<p class="footer-content align-center">{{ 'APP_NAME' | translate }} {{ 'labels.text.by' | translate }} Mifos</p>
</div>
+10
View File
@@ -52,6 +52,8 @@ export class FooterComponent implements OnInit, OnDestroy {
server = '';
/** Business Date */
businessDate: Date = null;
/** Tenant name */
tenant: string;
isBusinessDateEnabled = false;
isBusinessDateDefined = false;
@@ -87,6 +89,7 @@ export class FooterComponent implements OnInit, OnDestroy {
});
this.getConfigurations();
this.server = this.settingsService.server;
this.tenant = this.tenantIdentifier();
this.versionService.getBackendInfo().subscribe((data: any) => {
if (data.git && data.git.build && data.git.build.version) {
const buildVersion: string = data.git.build.version.split('-');
@@ -97,6 +100,13 @@ export class FooterComponent implements OnInit, OnDestroy {
}
}
tenantIdentifier() {
if (!this.settingsService.tenantIdentifier || this.settingsService.tenantIdentifier === '') {
return 'default';
}
return this.settingsService.tenantIdentifier;
}
ngOnDestroy() {
if (this.displayBackEndInfo) {
clearTimeout(this.timer);

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

+2
View File
@@ -3463,6 +3463,8 @@
"Delete Image": "Smazat obrázek",
"Delete Interest Rate Chart": "Smazat graf úrokových sazeb",
"Delete Standing Instruction": "Smazat stálý pokyn",
"Tenant": "Nájemce",
"to": "do",
"Deposit": "Vklad",
"Description is used to provide additional information regarding the purpose": "Popis slouží k poskytnutí dalších informací týkajících se účelu a vlastností produktu s opakovaným vkladem.",
"Due to regulatory requirements in some countries": "Vzhledem k regulačním požadavkům v některých zemích nemohou půjčky přesáhnout X dní, Fineract SOR je třeba rozšířit tak, aby podporoval definici, že půjčka má maximální délku a maximální délka této půjčky definuje délku poslední splátky, která bude kratší dobu než první splátky.",
+2
View File
@@ -3464,6 +3464,8 @@
"Delete Image": "Lösche Bild",
"Delete Interest Rate Chart": "Zinsdiagramm löschen",
"Delete Standing Instruction": "Ständige Anweisung löschen",
"Tenant": "Mieter",
"to": "zu",
"Deposit": "Kaution",
"Description is used to provide additional information regarding the purpose": "Die Beschreibung wird verwendet, um zusätzliche Informationen über den Zweck und die Eigenschaften des wiederkehrenden Einzahlungsprodukts bereitzustellen.",
"Due to regulatory requirements in some countries": "Aufgrund regulatorischer Anforderungen in einigen Ländern dürfen Kredite nicht länger als X Tage sein. Das Fineract SOR muss erweitert werden, um die Definition zu unterstützen, dass ein Kredit eine maximale Laufzeit hat und die maximale Laufzeit dieses Kredits die Länge der letzten Rate definiert, die a beträgt kürzerer Zeitraum als die ersten Raten.",
+2
View File
@@ -3454,6 +3454,8 @@
"Mandatory": "Mandatory",
"Voluntary": "Voluntary",
"Write a note": "Write a note",
"Tenant": "Tenant",
"To": "to",
"“Maker-Checker” principle requires every tasks": "The “Maker-Checker” principle requires every tasks to be completed by two people to reduce the chance of errors and misuse. One person initiates the process and the second completes it.",
"Buy Down Fees": "Buy Down Fees",
"Undo Write-off Description": "This action will reverse the write-off transaction and restore the loan to its previous active status. Please provide a note explaining the reason for this action.",
+2
View File
@@ -3348,6 +3348,8 @@
"Mandatory": "Obligatorio",
"Voluntary": "Voluntario",
"Write a note": "Escribe una nota",
"Tenant": "Inquilino",
"To": "a",
"“Maker-Checker” principle requires every tasks": "El principio \"Maker-Checker\" requiere que dos personas completen cada tarea para reducir la posibilidad de errores y uso indebido. Una persona inicia el proceso y la segunda lo completa.",
"Buy Down Fees": "Tarifas de compra",
"UploadDocumentHint": "Sube un PDF o imagen para generar una vista previa."
+2
View File
@@ -3350,6 +3350,8 @@
"Mandatory": "Obligatorio",
"Voluntary": "Voluntario",
"Write a note": "Escribe una nota",
"Tenant": "Inquilino",
"To": "a",
"“Maker-Checker” principle requires every tasks": "El principio \"Maker-Checker\" requiere que dos personas completen cada tarea para reducir la posibilidad de errores y uso indebido. Una persona inicia el proceso y la segunda lo completa.",
"Buy Down Fees": "Tarifas de compra",
"UploadDocumentHint": "Sube un PDF o imagen para generar una vista previa."
+2
View File
@@ -3347,6 +3347,8 @@
"Mandatory": "Obligatoire",
"Voluntary": "Volontaire",
"Write a note": "Écrire une note",
"Tenant": "Locataire",
"To": "À",
"“Maker-Checker” principle requires every tasks": "Le principe « Maker-Checker » exige que chaque tâche soit effectuée par deux personnes afin de réduire les risques d'erreurs et de mauvaise utilisation. Une personne lance le processus et la seconde le termine.",
"Buy Down Fees": "Frais de rachat",
"UploadDocumentHint": "Téléchargez un PDF ou une image pour générer un aperçu."
+2
View File
@@ -3348,6 +3348,8 @@
"Mandatory": "Obbligatorio",
"Voluntary": "Volontario",
"Write a note": "Scrivi una nota",
"Tenant": "Inquilino",
"To": "a",
"“Maker-Checker” principle requires every tasks": "Il principio “Maker-Checker” richiede che ogni attività venga completata da due persone per ridurre la possibilità di errori e usi impropri. Una persona avvia il processo e la seconda lo completa.",
"Buy Down Fees": "Commissioni di acquisto",
"UploadDocumentHint": "Carica un PDF o un'immagine per generare un'anteprima."
+2
View File
@@ -3348,6 +3348,8 @@
"Mandatory": "필수적인",
"Voluntary": "자발적인",
"Write a note": "메모 쓰기",
"Tenant": "임차인",
"To": "에게",
"“Maker-Checker” principle requires every tasks": "\"Maker-Checker\" 원칙은 오류와 오용 가능성을 줄이기 위해 모든 작업을 두 사람이 완료하도록 요구합니다. 한 사람이 프로세스를 시작하고 두 번째 사람이 프로세스를 완료합니다.",
"Buy Down Fees": "매입 수수료",
"UploadDocumentHint": "미리보기를 생성하려면 PDF 또는 이미지를 업로드하세요."
+2
View File
@@ -3348,6 +3348,8 @@
"Mandatory": "Privaloma",
"Voluntary": "Savanoriškas",
"Write a note": "Parašykite pastabą",
"Tenant": "Nuomininkas",
"To": "Kam",
"“Maker-Checker” principle requires every tasks": "„Maker-Checker“ principas reikalauja, kad kiekvieną užduotį atliktų du žmonės, kad būtų sumažinta klaidų ir netinkamo naudojimo galimybė. Vienas asmuo pradeda procesą, o antrasis jį užbaigia.",
"Buy Down Fees": "Išpirkimo mokesčiai",
"UploadDocumentHint": "Įkelkite PDF arba vaizdą, kad sugeneruotumėte peržiūrą."
+2
View File
@@ -3348,6 +3348,8 @@
"Mandatory": "Obligāts",
"Voluntary": "Brīvprātīgi",
"Write a note": "Uzrakstiet piezīmi",
"Tenant": "Īrnieks",
"To": "Līdz",
"“Maker-Checker” principle requires every tasks": "“Maker-Checker” princips paredz, ka katrs uzdevums ir jāveic diviem cilvēkiem, lai samazinātu kļūdu un nepareizas lietošanas iespējamību. Viens cilvēks uzsāk procesu, bet otrs to pabeidz.",
"Buy Down Fees": "Izpirkšanas maksas",
"UploadDocumentHint": "Augšupielādējiet PDF vai attēlu, lai izveidotu priekšskatījumu."
+2
View File
@@ -3347,6 +3347,8 @@
"Mandatory": "अनिवार्य",
"Voluntary": "स्वैच्छिक",
"Write a note": "नोट लेख्नुहोस्",
"Tenant": "किरायेदार",
"To": "लाई",
"“Maker-Checker” principle requires every tasks": "\"मेकर-चेकर\" सिद्धान्तले त्रुटि र दुरुपयोगको सम्भावना कम गर्न प्रत्येक कार्यहरू दुई व्यक्तिद्वारा पूरा गर्न आवश्यक छ। एक व्यक्तिले प्रक्रिया सुरु गर्छ र दोस्रोले यसलाई पूरा गर्दछ।",
"Buy Down Fees": "खरीद शुल्क",
"UploadDocumentHint": "पूर्वावलोकन उत्पन्न गर्न PDF वा छवि अपलोड गर्नुहोस्।"
+2
View File
@@ -3348,6 +3348,8 @@
"Mandatory": "Obrigatório",
"Voluntary": "Voluntário",
"Write a note": "Escreva uma nota",
"Tenant": "Inquilino",
"To": "Para",
"“Maker-Checker” principle requires every tasks": "O princípio “Maker-Checker” exige que todas as tarefas sejam concluídas por duas pessoas para reduzir a chance de erros e uso indevido. Uma pessoa inicia o processo e a segunda o conclui.",
"Buy Down Fees": "Taxas de compra",
"UploadDocumentHint": "Carregue um PDF ou imagem para gerar uma pré-visualização."
+2
View File
@@ -3345,6 +3345,8 @@
"Mandatory": "Lazima",
"Voluntary": "Kwa hiari",
"Write a note": "Andika dokezo",
"Tenant": "Mpangaji",
"To": "Kwa",
"“Maker-Checker” principle requires every tasks": "Kanuni ya \"Mtengenezaji-Kikagua\" inahitaji kila kazi kukamilishwa na watu wawili ili kupunguza uwezekano wa makosa na matumizi mabaya. Mtu mmoja anaanzisha mchakato na wa pili anakamilisha.",
"Buy Down Fees": "Ada za Ununuzi",
"UploadDocumentHint": "Pakia PDF au picha ili kutoa hakikisho."