WEB-636 feat(system): implement system information section (#3207)

WEB-636 fix(system): address code review feedback for stylelint and link security
This commit is contained in:
Shubham Kumar
2026-02-22 15:11:07 -06:00
committed by GitHub
parent 4a3417d617
commit cd190b385a
9 changed files with 267 additions and 2 deletions
+2
View File
@@ -114,6 +114,7 @@ import {
faAddressCard,
faKeyboard,
faInfo,
faInfoCircle,
faTasks,
faCoins,
faPiggyBank,
@@ -267,6 +268,7 @@ export class IconsModule {
faAddressCard,
faKeyboard,
faInfo,
faInfoCircle,
faTasks,
faCoins,
faPiggyBank,
@@ -0,0 +1,50 @@
<!--
Copyright since 2025 Mifos Initiative
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->
<div class="container">
<mat-card>
<div class="system-info-section">
<table class="system-info-table">
<tr>
<td class="info-label">{{ 'labels.version.Tenant' | translate }}</td>
<td class="info-value">{{ tenant }}</td>
</tr>
<tr>
<td class="info-label">{{ 'labels.version.Mifos WebApp' | translate }}</td>
<td class="info-value">{{ mifosVersion }}</td>
</tr>
<tr>
<td class="info-label">{{ 'labels.version.Apache Fineract' | translate }}</td>
<td class="info-value">{{ fineractVersion }}</td>
</tr>
<tr>
<td class="info-label">{{ 'labels.version.Server' | translate }}</td>
<td class="info-value">{{ server }}</td>
</tr>
</table>
</div>
<div class="licensing-section">
<h2>{{ 'labels.heading.Software Licensing' | translate }}</h2>
<p [innerHTML]="'labels.licensing.Apache Fineract Description' | translate"></p>
<p [innerHTML]="'labels.licensing.Mifos X Distribution' | translate"></p>
<p [innerHTML]="'labels.licensing.Legacy Codebase' | translate"></p>
<ul>
<li [innerHTML]="'labels.licensing.How to License Code' | translate"></li>
<li [innerHTML]="'labels.licensing.Contributor Agreement' | translate"></li>
<li [innerHTML]="'labels.licensing.License FAQs' | translate"></li>
<li [innerHTML]="'labels.licensing.Adding External Software' | translate"></li>
<li [innerHTML]="'labels.licensing.Code of Conduct' | translate"></li>
</ul>
</div>
</mat-card>
</div>
@@ -0,0 +1,111 @@
/**
* Copyright since 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
.system-info-section {
padding: 24px 16px;
}
.system-info-table {
width: 100%;
max-width: 600px;
border-collapse: collapse;
tr {
border-bottom: 1px solid var(--md-sys-color-outline-variant, #e0e0e0);
}
td {
padding: 12px 16px;
}
.info-label {
font-weight: 500;
color: var(--md-sys-color-on-surface-variant, #555);
width: 40%;
}
.info-value {
font-weight: 600;
color: var(--md-sys-color-on-surface, #333);
}
}
.licensing-section {
padding: 16px 24px;
h2 {
color: #4caf50;
margin-top: 24px;
margin-bottom: 16px;
font-size: 1.5rem;
font-weight: 400;
}
p {
line-height: 1.6;
margin-bottom: 12px;
color: var(--md-sys-color-on-surface-variant, #555);
}
// stylelint-disable-next-line selector-pseudo-element-no-unknown
::ng-deep a {
color: #4caf50;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
ul {
padding-left: 24px;
margin-top: 12px;
li {
margin-bottom: 8px;
line-height: 1.5;
color: var(--md-sys-color-on-surface-variant, #555);
}
}
}
// Dark theme support
:host-context(.dark-theme) {
.system-info-table {
tr {
border-bottom-color: rgb(255 255 255 / 30%);
}
.info-label {
color: #bbb;
}
.info-value {
color: rgb(255 255 255 / 87%);
}
}
.licensing-section {
h2 {
color: #66bb6a;
}
p {
color: rgb(255 255 255 / 70%);
}
// stylelint-disable-next-line selector-pseudo-element-no-unknown
::ng-deep a {
color: #0098ff;
}
ul li {
color: rgb(255 255 255 / 70%);
}
}
}
@@ -0,0 +1,45 @@
/**
* Copyright since 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
import { Component, OnInit, inject } from '@angular/core';
import { MatCard } from '@angular/material/card';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
import { SettingsService } from 'app/settings/settings.service';
import { VersionService } from 'app/system/version.service';
import { environment } from '../../../environments/environment';
@Component({
selector: 'mifosx-system-information',
templateUrl: './system-information.component.html',
styleUrls: ['./system-information.component.scss'],
imports: [
...STANDALONE_SHARED_IMPORTS,
MatCard
]
})
export class SystemInformationComponent implements OnInit {
private settingsService = inject(SettingsService);
private versionService = inject(VersionService);
tenant = '';
mifosVersion = '';
fineractVersion = '';
server = '';
ngOnInit(): void {
this.tenant = this.settingsService.tenantIdentifier || 'default';
this.mifosVersion = environment.version;
this.server = this.settingsService.server;
this.versionService.getBackendInfo().subscribe((data: any) => {
if (data.git && data.git.build && data.git.build.version) {
this.fineractVersion = data.git.build.version;
}
});
}
}
+6
View File
@@ -54,6 +54,7 @@ import { EditRoleComponent } from './roles-and-permissions/edit-role/edit-role.c
import { RolesAndPermissionsComponent } from './roles-and-permissions/roles-and-permissions.component';
import { ViewRoleComponent } from './roles-and-permissions/view-role/view-role.component';
import { SystemComponent } from './system.component';
import { SystemInformationComponent } from './system-information/system-information.component';
/** Custom Resolvers */
import { AccountNumberPreferencesResolver } from './account-number-preferences/account-number-preferences.resolver';
@@ -582,6 +583,11 @@ const routes: Routes = [
}
]
},
{
path: 'system-information',
component: SystemInformationComponent,
data: { title: 'System Information', breadcrumb: 'System Information' }
},
{
path: 'audit-trails',
data: { title: 'Audit Trails', breadcrumb: 'Audit Trails' },
+34
View File
@@ -290,6 +290,40 @@
</div>
</div>
</mat-list-item>
<mat-list-item [routerLink]="['system-information']">
<div class="menu-list-item-content">
<div class="menu-left-section" [routerLink]="['system-information']">
<mat-icon matListIcon>
<fa-icon icon="info-circle" size="sm"></fa-icon>
</mat-icon>
<div matLine>
{{ 'labels.heading.System Information' | translate }}
@if (arrowBooleans[15]) {
<p matLine [routerLink]="['system-information']" class="menu-explanation">
{{ 'labels.text.View system version, server and licensing information' | translate }}
</p>
}
</div>
</div>
<div class="menu-right-section">
@if (!arrowBooleans[15]) {
<fa-icon
(click)="arrowBooleansToggle(15); $event.stopPropagation()"
icon="arrow-down"
size="md"
></fa-icon>
}
@if (arrowBooleans[15]) {
<fa-icon
(click)="arrowBooleansToggle(15); $event.stopPropagation()"
icon="arrow-up"
size="md"
></fa-icon>
}
</div>
</div>
</mat-list-item>
</mat-nav-list>
</div>
+1 -1
View File
@@ -69,7 +69,7 @@ export class SystemComponent implements AfterViewInit {
@ViewChild('templateManageReports') templateManageReports: TemplateRef<any>;
// Initialize an array of 15 boolean values, all set to false
isDisabled: boolean = true;
arrowBooleans: boolean[] = new Array(15).fill(false);
arrowBooleans: boolean[] = new Array(16).fill(false);
/**
* Popover function
+3 -1
View File
@@ -85,6 +85,7 @@ import { CustomParametersTableComponent } from './manage-jobs/scheduler-jobs/cus
import { ErrorLogPopoverComponent } from './manage-jobs/scheduler-jobs/error-log-popover/error-log-popover.component';
import { RunSelectedJobsPopoverComponent } from './manage-jobs/scheduler-jobs/run-selected-jobs-popover/run-selected-jobs-popover.component';
import { RunSelectedJobsTableComponent } from './manage-jobs/scheduler-jobs/run-selected-jobs-popover/run-selected-jobs-table/run-selected-jobs-table.component';
import { SystemInformationComponent } from './system-information/system-information.component';
@NgModule({
imports: [
@@ -159,7 +160,8 @@ import { RunSelectedJobsTableComponent } from './manage-jobs/scheduler-jobs/run-
CustomParametersTableComponent,
ErrorLogPopoverComponent,
RunSelectedJobsPopoverComponent,
RunSelectedJobsTableComponent
RunSelectedJobsTableComponent,
SystemInformationComponent
]
})
export class SystemModule {}