Login form with Tenant dropdown menu
This commit is contained in:
@@ -133,11 +133,17 @@ https://localhost:8443
|
||||
```
|
||||
FINERACT_PLATFORM_TENANT_IDENTIFIER
|
||||
```
|
||||
Fineract Tenant identifier to be used, It must be aligned with the Fineract `tenants` table. Default value:
|
||||
Fineract Tenant identifier to be used by default, It must be aligned with the Fineract `tenants` table. Default value:
|
||||
```
|
||||
default
|
||||
```
|
||||
|
||||
```
|
||||
FINERACT_PLATFORM_TENANTS_IDENTIFIER
|
||||
```
|
||||
Fineract Tenant identifier list to be used, Those must be aligned with the Fineract `tenants` table.
|
||||
|
||||
|
||||
Setting for Languages (i18n) still under development
|
||||
```
|
||||
MIFOS_DEFAULT_LANGUAGE=en-US
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
|
||||
# Fineract URLs list delimited by colon
|
||||
FINERACT_API_URLS=https://dev.mifos.io,https://demo.mifos.io,https://qa.mifos.io,https://staging.mifos.io,https://mobile.mifos.io,https://demo.fineract.dev,https://localhost:8443
|
||||
|
||||
FINERACT_API_URL=https://localhost:8443
|
||||
@@ -9,6 +10,9 @@ FINERACT_API_VERSION=/v1
|
||||
|
||||
FINERACT_PLATFORM_TENANT_IDENTIFIER=default
|
||||
|
||||
# Tenant Identifiers list delimited by colon
|
||||
FINERACT_PLATFORM_TENANTS_IDENTIFIER=default
|
||||
|
||||
MIFOS_DEFAULT_LANGUAGE=en-US
|
||||
|
||||
MIFOS_SUPPORTED_LANGUAGES=en-US,fr-FR
|
||||
|
||||
@@ -100,12 +100,12 @@ export class CreateClientComponent {
|
||||
|
||||
setDatatables(): void {
|
||||
this.datatables = [];
|
||||
let legalFormTypeVal = 'Person';
|
||||
let legalFormTypeVal = 'person';
|
||||
if (this.legalFormType === 2) {
|
||||
legalFormTypeVal = 'Entity';
|
||||
legalFormTypeVal = 'entity';
|
||||
}
|
||||
this.clientTemplate.datatables.forEach((datatable: any) => {
|
||||
if (datatable.entitySubType === legalFormTypeVal) {
|
||||
if (datatable.entitySubType.toLowerCase() === legalFormTypeVal) {
|
||||
this.datatables.push(datatable);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -5,10 +5,11 @@ import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/c
|
||||
/** rxjs Imports */
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
/** Environment Configuration */
|
||||
/** Custom Imports */
|
||||
import { environment } from '../../../environments/environment';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
|
||||
/** Http request options headers. */
|
||||
/** Http request (default) options headers. */
|
||||
const httpOptions = {
|
||||
headers: {
|
||||
'Fineract-Platform-TenantId': environment.fineractPlatformTenantId
|
||||
@@ -26,12 +27,15 @@ const twoFactorAccessTokenHeader = 'Fineract-Platform-TFA-Token';
|
||||
@Injectable()
|
||||
export class AuthenticationInterceptor implements HttpInterceptor {
|
||||
|
||||
constructor() {}
|
||||
constructor(private settingsService: SettingsService) {}
|
||||
|
||||
/**
|
||||
* Intercepts a Http request and sets the request headers.
|
||||
*/
|
||||
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
if (this.settingsService.tenantIdentifier) {
|
||||
httpOptions.headers['Fineract-Platform-TenantId'] = this.settingsService.tenantIdentifier;
|
||||
}
|
||||
request = request.clone({ setHeaders: httpOptions.headers });
|
||||
return next.handle(request);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<img src="assets/images/user_placeholder.png" alt="app-user-photo">
|
||||
</div>
|
||||
<span class="app-user-name mb-05">
|
||||
{{ username }}
|
||||
{{ tenantIdentifier }} / {{ username }}
|
||||
</span>
|
||||
<div #userPanel class="app-user-controls">
|
||||
<button class="xs-button" mat-icon-button matTooltip="{{ 'tooltips.Settings' | translate }}" [routerLink]="['/settings']">
|
||||
|
||||
@@ -14,6 +14,7 @@ import { ConfigurationWizardService } from '../../../configuration-wizard/config
|
||||
|
||||
/** Custom Imports */
|
||||
import { frequentActivities } from './frequent-activities';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
|
||||
/**
|
||||
* Sidenav component.
|
||||
@@ -51,12 +52,14 @@ export class SidenavComponent implements OnInit, AfterViewInit {
|
||||
* @param {Router} router Router for navigation.
|
||||
* @param {MatDialog} dialog Mat Dialog
|
||||
* @param {AuthenticationService} authenticationService Authentication Service.
|
||||
* @param {SettingsService} settingsService Settings Service.
|
||||
* @param {ConfigurationWizardService} configurationWizardService ConfigurationWizard Service.
|
||||
* @param {PopoverService} popoverService PopoverService.
|
||||
*/
|
||||
constructor(private router: Router,
|
||||
public dialog: MatDialog,
|
||||
private authenticationService: AuthenticationService,
|
||||
private settingsService: SettingsService,
|
||||
private configurationWizardService: ConfigurationWizardService,
|
||||
private popoverService: PopoverService) {
|
||||
this.userActivity = JSON.parse(localStorage.getItem('mifosXLocation'));
|
||||
@@ -207,4 +210,12 @@ export class SidenavComponent implements OnInit, AfterViewInit {
|
||||
this.router.onSameUrlNavigation = 'reload';
|
||||
this.router.navigate(['/home']);
|
||||
}
|
||||
|
||||
get tenantIdentifier(): string {
|
||||
if (!this.settingsService.tenantIdentifier || this.settingsService.tenantIdentifier === '') {
|
||||
return 'default';
|
||||
}
|
||||
return this.settingsService.tenantIdentifier;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<form fxLayout="column" [formGroup]="loginForm" (ngSubmit)="login()" id="login-form">
|
||||
|
||||
<mat-form-field fxFlexAlign="center" class="login-input">
|
||||
<span matPrefix>
|
||||
<fa-icon icon="user-circle" size="lg"></fa-icon>
|
||||
<span matPrefix class="m-r-10">
|
||||
<fa-icon icon="user-circle" size="lg"></fa-icon>
|
||||
</span>
|
||||
<mat-label>{{ 'labels.inputs.Username' | translate }}</mat-label>
|
||||
<input matInput type="text" autocomplete="off" formControlName="username">
|
||||
@@ -12,8 +12,8 @@
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field fxFlexAlign="center" class="login-input">
|
||||
<span matPrefix>
|
||||
<fa-icon icon="lock" size="lg"></fa-icon>
|
||||
<span matPrefix class="m-r-10">
|
||||
<fa-icon icon="lock" size="lg"></fa-icon>
|
||||
</span>
|
||||
<mat-label>{{ 'labels.inputs.Password' | translate }}</mat-label>
|
||||
<input matInput type="{{ passwordInputType }}" formControlName="password">
|
||||
|
||||
@@ -43,6 +43,11 @@
|
||||
<img src="assets/images/mifos-logo-flat.png" alt="{{ 'APP_NAME' | translate }} Logo" class="img-container">
|
||||
</div>
|
||||
|
||||
<!-- Tenant Identifier Name -->
|
||||
<div fxLayout="row" fxLayoutAlign="center center" fxFlex="1 0 auto">
|
||||
<mifosx-tenant-selector></mifosx-tenant-selector>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
Type of Form:
|
||||
Login
|
||||
|
||||
@@ -76,7 +76,7 @@ export class AllocateCashComponent implements OnInit {
|
||||
const locale = this.settingsService.language.code;
|
||||
const dateFormat = this.settingsService.dateFormat;
|
||||
const txnDate = this.allocateCashForm.value.txnDate;
|
||||
if (allocateCashFormData.closureDate instanceof Date) {
|
||||
if (allocateCashFormData.txnDate instanceof Date) {
|
||||
allocateCashFormData.txnDate = this.dateUtils.formatDate(txnDate, dateFormat);
|
||||
}
|
||||
const data = {
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;" class="select-row" [routerLink]="[row.id]"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
@@ -16,6 +16,14 @@
|
||||
|
||||
<div fxLayout="row wrap" class="content">
|
||||
|
||||
<div fxFlex="50%" class="header">
|
||||
Tenant Id
|
||||
</div>
|
||||
|
||||
<div fxFlex="50%">
|
||||
{{ tenantIdentifier }}
|
||||
</div>
|
||||
|
||||
<div fxFlex="50%" class="header">
|
||||
User Id
|
||||
</div>
|
||||
@@ -81,4 +89,4 @@
|
||||
|
||||
</mat-card>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -8,6 +8,7 @@ import { Router } from '@angular/router';
|
||||
import { AuthenticationService } from 'app/core/authentication/authentication.service';
|
||||
import { ChangePasswordDialogComponent } from 'app/shared/change-password-dialog/change-password-dialog.component';
|
||||
import { UserService } from 'app/self-service/users/user.service';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
|
||||
/**
|
||||
* Profile Component.
|
||||
@@ -36,9 +37,10 @@ export class ProfileComponent implements OnInit {
|
||||
* @param {MatDialog} dialog Mat Dialog
|
||||
*/
|
||||
constructor(private authenticationService: AuthenticationService,
|
||||
private userService: UserService,
|
||||
private router: Router,
|
||||
public dialog: MatDialog) {
|
||||
private settingsService: SettingsService,
|
||||
private userService: UserService,
|
||||
private router: Router,
|
||||
public dialog: MatDialog) {
|
||||
this.profileData = authenticationService.getCredentials();
|
||||
}
|
||||
|
||||
@@ -66,4 +68,8 @@ export class ProfileComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
get tenantIdentifier(): string {
|
||||
return this.settingsService.tenantIdentifier || 'default';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -63,6 +63,22 @@ export class SettingsService {
|
||||
localStorage.setItem('mifosXServers', JSON.stringify(list));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets Tenant Identifiers list setting throughout the app.
|
||||
* @param {string[]} list List of default tenants
|
||||
*/
|
||||
setTenantIdentifiers(list: string[]) {
|
||||
localStorage.setItem('mifosXTenantIdentifiers', JSON.stringify(list));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets Tenant Identifier setting throughout the app.
|
||||
* @param {string} Tenant Identifier
|
||||
*/
|
||||
setTenantIdentifier(tenantIdentifier: string) {
|
||||
localStorage.setItem('mifosXTenantIdentifier', tenantIdentifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets server Date setting for max datepicker, default today
|
||||
* @param {string} date
|
||||
@@ -141,6 +157,20 @@ export class SettingsService {
|
||||
return this.maxAllowedDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of Tenant Identifiers
|
||||
*/
|
||||
get tenantIdentifiers(): any {
|
||||
return JSON.parse(localStorage.getItem('mifosXTenantIdentifiers'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Tenant Identifier
|
||||
*/
|
||||
get tenantIdentifier(): string {
|
||||
return localStorage.getItem('mifosXTenantIdentifier');
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate If the enable_business_date configuration is enabled or disabled.
|
||||
*/
|
||||
|
||||
@@ -21,6 +21,7 @@ import { NotificationsTrayComponent } from './notifications-tray/notifications-t
|
||||
import { SearchToolComponent } from './search-tool/search-tool.component';
|
||||
import { KeyboardShortcutsDialogComponent } from './keyboard-shortcuts-dialog/keyboard-shortcuts-dialog.component';
|
||||
import { ServerSelectorComponent } from './server-selector/server-selector.component';
|
||||
import { TenantSelectorComponent } from './tenant-selector/tenant-selector.component';
|
||||
|
||||
/** Custom Modules */
|
||||
import { IconsModule } from './icons.module';
|
||||
@@ -57,7 +58,8 @@ import { TranslateModule } from '@ngx-translate/core';
|
||||
ErrorDialogComponent,
|
||||
NotificationsTrayComponent,
|
||||
SearchToolComponent,
|
||||
ServerSelectorComponent
|
||||
ServerSelectorComponent,
|
||||
TenantSelectorComponent
|
||||
],
|
||||
exports: [
|
||||
FileUploadComponent,
|
||||
@@ -73,7 +75,8 @@ import { TranslateModule } from '@ngx-translate/core';
|
||||
MaterialModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
TranslateModule
|
||||
TranslateModule,
|
||||
TenantSelectorComponent
|
||||
]
|
||||
})
|
||||
export class SharedModule { }
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<mat-form-field fxFlexAlign="center" id="tenant-selector">
|
||||
<span matPrefix class="m-r-10">
|
||||
<fa-icon icon="building" size="lg"></fa-icon>
|
||||
</span>
|
||||
<mat-label>{{ 'labels.inputs.Tenant' | translate }}</mat-label>
|
||||
<mat-select [disabled]="!allowSelection()" [formControl]="tenantSelector" (selectionChange)="setTenantIdentifier()" class="tenantselector">
|
||||
<mat-option *ngFor="let tenant of tenants" [value]="tenant">
|
||||
{{ tenant }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
@@ -0,0 +1,5 @@
|
||||
#tenant-selector,
|
||||
.tenantselector {
|
||||
width: 14rem;
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { TenantSelectorComponent } from './tenant-selector.component';
|
||||
|
||||
describe('TenantSelectorComponent', () => {
|
||||
let component: TenantSelectorComponent;
|
||||
let fixture: ComponentFixture<TenantSelectorComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ TenantSelectorComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(TenantSelectorComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,42 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
|
||||
@Component({
|
||||
selector: 'mifosx-tenant-selector',
|
||||
templateUrl: './tenant-selector.component.html',
|
||||
styleUrls: ['./tenant-selector.component.scss']
|
||||
})
|
||||
export class TenantSelectorComponent implements OnInit {
|
||||
|
||||
/** Tenant selector form control. */
|
||||
tenantSelector = new FormControl();
|
||||
|
||||
/**
|
||||
* Sets the Tenant Identifier of the application in the selector on initial setup.
|
||||
* @param {SettingsService} settingsService Settings Service.
|
||||
*/
|
||||
constructor(private settingsService: SettingsService) {
|
||||
this.tenantSelector.setValue(this.settingsService.tenantIdentifier);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the languages supported by the application.
|
||||
* @return {string[]} Supported languages.
|
||||
*/
|
||||
get tenants(): string[] {
|
||||
return this.settingsService.tenantIdentifiers || [];
|
||||
}
|
||||
|
||||
setTenantIdentifier(): void {
|
||||
this.settingsService.setTenantIdentifier(this.tenantSelector.value);
|
||||
}
|
||||
|
||||
allowSelection(): boolean {
|
||||
return (this.tenants.length > 1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -150,6 +150,9 @@ export class WebAppComponent implements OnInit {
|
||||
this.settingsService.setBusinessDate(this.dateUtils.formatDate(new Date(), SettingsService.businessDateFormat));
|
||||
// Set the server list from the env var FINERACT_API_URLS
|
||||
this.settingsService.setServers(environment.baseApiUrls.split(','));
|
||||
// Set the Tenant Identifier(s) list from the env var
|
||||
this.settingsService.setTenantIdentifier(environment.fineractPlatformTenantId || 'default');
|
||||
this.settingsService.setTenantIdentifiers(environment.fineractPlatformTenantIds.split(','));
|
||||
}
|
||||
|
||||
logout() {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
window["env"]["apiVersion"] = '$FINERACT_API_VERSION';
|
||||
|
||||
window["env"]["fineractPlatformTenantId"] = '$FINERACT_PLATFORM_TENANT_IDENTIFIER';
|
||||
window["env"]["fineractPlatformTenantIds"] = '$FINERACT_PLATFORM_TENANTS_IDENTIFIER';
|
||||
|
||||
// Language Environment variables
|
||||
window["env"]["defaultLanguage"] = '$MIFOS_DEFAULT_LANGUAGE';
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"is required": "is required"
|
||||
},
|
||||
"inputs": {
|
||||
"Tenant": "Tenant",
|
||||
"Language": "Language",
|
||||
"Server": "Server",
|
||||
"Url": "Url",
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"is required": "es requerido"
|
||||
},
|
||||
"inputs": {
|
||||
"Tenant": "Entidad",
|
||||
"Language": "Lenguaje",
|
||||
"Server": "Servidor",
|
||||
"Url": "Url",
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"is required": "is required"
|
||||
},
|
||||
"inputs": {
|
||||
"Tenant": "Tenant",
|
||||
"Language": "Language",
|
||||
"Server": "Server",
|
||||
"Url": "Url",
|
||||
|
||||
@@ -7,6 +7,7 @@ export const environment = {
|
||||
hash: env.mifos_x.hash,
|
||||
// For connecting to server running elsewhere update the tenant identifier
|
||||
fineractPlatformTenantId: window['env']['fineractPlatformTenantId'] || 'default',
|
||||
fineractPlatformTenantIds: window['env']['fineractPlatformTenantIds'] || 'default',
|
||||
// For connecting to others servers running elsewhere update the base API URL
|
||||
baseApiUrls: window['env']['fineractApiUrls'] ||
|
||||
'https://dev.mifos.io,https://demo.mifos.io,https://qa.mifos.io,https://staging.mifos.io,https://mobile.mifos.io,https://demo.fineract.dev,https://localhost:8443',
|
||||
|
||||
@@ -12,6 +12,7 @@ export const environment = {
|
||||
hash: env.mifos_x.hash,
|
||||
// For connecting to server running elsewhere update the tenant identifier
|
||||
fineractPlatformTenantId: window['env']['fineractPlatformTenantId'] || 'default',
|
||||
fineractPlatformTenantIds: window['env']['fineractPlatformTenantIds'] || 'default',
|
||||
// For connecting to others servers running elsewhere update the base API URL
|
||||
baseApiUrls: window['env']['fineractApiUrls'] ||
|
||||
'https://dev.mifos.io,https://demo.mifos.io,https://qa.mifos.io,https://staging.mifos.io,https://mobile.mifos.io,https://demo.fineract.dev,https://localhost:8443',
|
||||
|
||||
Reference in New Issue
Block a user