diff --git a/ogWebconsole/src/app/app.module.ts b/ogWebconsole/src/app/app.module.ts index dcdd97f..4a0ed99 100644 --- a/ogWebconsole/src/app/app.module.ts +++ b/ogWebconsole/src/app/app.module.ts @@ -133,6 +133,7 @@ import { ManageClientComponent } from './components/groups/shared/clients/manage import { ConvertImageComponent } from './components/repositories/convert-image/convert-image.component'; import { registerLocaleData } from '@angular/common'; import localeEs from '@angular/common/locales/es'; +import { GlobalStatusComponent } from './components/global-status/global-status.component'; export function HttpLoaderFactory(http: HttpClient) { return new TranslateHttpLoader(http, './locale/', '.json'); @@ -225,7 +226,8 @@ registerLocaleData(localeEs, 'es-ES'); BackupImageComponent, ShowClientsComponent, OperationResultDialogComponent, - ConvertImageComponent + ConvertImageComponent, + GlobalStatusComponent ], bootstrap: [AppComponent], imports: [BrowserModule, diff --git a/ogWebconsole/src/app/components/global-status/global-status.component.css b/ogWebconsole/src/app/components/global-status/global-status.component.css new file mode 100644 index 0000000..0267674 --- /dev/null +++ b/ogWebconsole/src/app/components/global-status/global-status.component.css @@ -0,0 +1,22 @@ +.action-container { + display: flex; + justify-content: flex-end; + gap: 1em; + padding: 1.5em; +} + +.status-led { + width: 10px; + height: 10px; + border-radius: 50%; + display: inline-block; + margin-right: 10px; +} + +.status-led.active { + background-color: green; +} + +.status-led.inactive { + background-color: red; +} \ No newline at end of file diff --git a/ogWebconsole/src/app/components/global-status/global-status.component.html b/ogWebconsole/src/app/components/global-status/global-status.component.html new file mode 100644 index 0000000..2b08c03 --- /dev/null +++ b/ogWebconsole/src/app/components/global-status/global-status.component.html @@ -0,0 +1,66 @@ +
+

Estado global de la aplicación

+
+ + + + +
+ +
+

{{ 'diskUsageTitle' | translate }}

+ + +
+

{{ 'totalLabel' | translate }}: {{ formatBytes(ogBootDiskUsage.total) }}

+

{{ 'usedLabel' | translate }}: {{ formatBytes(ogBootDiskUsage.used) }}

+

{{ 'availableLabel' | translate }}: {{ formatBytes(ogBootDiskUsage.available) }}

+

{{ 'freeLabel' | translate }}: {{ ogBootDiskUsage.percentage }}%

+
+
+ + +
+

{{ 'servicesTitle' | translate }}

+
    +
  • + + {{ service.name }}: {{ service.status | translate }} +
  • +
+
+ + +
+

{{ 'installedOglivesTitle' | translate }}

+ + + + + + + + + + + + + + + + + +
{{ 'idLabel' | translate }}{{ 'kernelLabel' | translate }}{{ 'architectureLabel' | translate }}{{ 'revisionLabel' | translate }}
{{ oglive.id }}{{ oglive.kernel }}{{ oglive.architecture }}{{ oglive.revision }}
+
+
+
+ Content 2 + Content 3 +
+
+ + + \ No newline at end of file diff --git a/ogWebconsole/src/app/components/global-status/global-status.component.spec.ts b/ogWebconsole/src/app/components/global-status/global-status.component.spec.ts new file mode 100644 index 0000000..5d993e0 --- /dev/null +++ b/ogWebconsole/src/app/components/global-status/global-status.component.spec.ts @@ -0,0 +1,49 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { ToastrModule } from 'ngx-toastr'; +import { MatDialogModule } from '@angular/material/dialog'; +import { MatTabsModule } from '@angular/material/tabs'; +import { GlobalStatusComponent } from './global-status.component'; +import { ConfigService } from '@services/config.service'; +import { LoadingComponent } from '../../shared/loading/loading.component'; +import { TranslateModule } from '@ngx-translate/core'; +import { NgxChartsModule } from '@swimlane/ngx-charts'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; + +describe('GlobalStatusComponent', () => { + let component: GlobalStatusComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + const mockConfigService = { + apiUrl: 'http://mock-api-url' + }; + + await TestBed.configureTestingModule({ + declarations: [GlobalStatusComponent, LoadingComponent], + imports: [ + HttpClientTestingModule, + ToastrModule.forRoot(), + MatDialogModule, + MatTabsModule, + TranslateModule.forRoot(), + NgxChartsModule, + BrowserAnimationsModule + ], + providers: [ + { provide: ConfigService, useValue: mockConfigService } + ], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + + fixture = TestBed.createComponent(GlobalStatusComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/ogWebconsole/src/app/components/global-status/global-status.component.ts b/ogWebconsole/src/app/components/global-status/global-status.component.ts new file mode 100644 index 0000000..2efc1f4 --- /dev/null +++ b/ogWebconsole/src/app/components/global-status/global-status.component.ts @@ -0,0 +1,77 @@ +import { HttpClient } from '@angular/common/http'; +import { Component, OnInit } from '@angular/core'; +import { ConfigService } from '@services/config.service'; +import { ToastrService } from 'ngx-toastr'; + +@Component({ + selector: 'app-global-status', + templateUrl: './global-status.component.html', + styleUrl: './global-status.component.css' +}) +export class GlobalStatusComponent implements OnInit { + baseUrl: string; + ogBootApiUrl: string; + loading: boolean = false; + ogBootDiskUsage: any = {}; + ogBootSubnets: any[] = []; + ogBootServicesStatus: any = {}; + installedOgLives: any[] = []; + diskUsageChartData: any[] = []; + gradient: boolean = true; + showLabels: boolean = true; + isDoughnut: boolean = true; + colorScheme: any = { + domain: ['#df200d', '#26a700'] + }; + view: [number, number] = [1100, 500]; + + constructor( + private configService: ConfigService, + private http: HttpClient, + private toastService: ToastrService + ) { + this.baseUrl = this.configService.apiUrl; + this.ogBootApiUrl = `${this.baseUrl}/og-boot/status`; + } + + ngOnInit(): void { + + } + + loadOgBootStatus(): void { + this.loading = true; + this.http.get(this.ogBootApiUrl).subscribe({ + next: data => { + this.ogBootDiskUsage = data.message.disk_usage; + this.ogBootSubnets = data.message.subnets; + this.ogBootServicesStatus = data.message.service_status; + this.installedOgLives = data.message.installed_oglives; + this.loading = false; + }, + error: error => { + this.toastService.error('Error al sincronizar ogBoot'); + console.log(error); + this.loading = false; + } + }); + } + + getServices(): { name: string, status: string }[] { + return Object.keys(this.ogBootServicesStatus).map(key => ({ + name: key, + status: this.ogBootServicesStatus[key] + })) + } + + formatBytes(bytes: number): string { + if (bytes >= 1e9) { + return (bytes / 1e9).toFixed(2) + ' GB'; + } else if (bytes >= 1e6) { + return (bytes / 1e6).toFixed(2) + ' MB'; + } else if (bytes >= 1e3) { + return (bytes / 1e3).toFixed(2) + ' KB'; + } else { + return bytes + ' B'; + } + } +} diff --git a/ogWebconsole/src/app/components/groups/groups.component.ts b/ogWebconsole/src/app/components/groups/groups.component.ts index c2abbe5..56393b4 100644 --- a/ogWebconsole/src/app/components/groups/groups.component.ts +++ b/ogWebconsole/src/app/components/groups/groups.component.ts @@ -17,13 +17,14 @@ import { DeleteModalComponent } from '../../shared/delete_modal/delete-modal/del import { ClassroomViewDialogComponent } from './shared/classroom-view/classroom-view-modal'; import { MatSort } from '@angular/material/sort'; import { MatTableDataSource } from '@angular/material/table'; -import { MatPaginator, PageEvent } from '@angular/material/paginator'; +import { PageEvent } from '@angular/material/paginator'; import { CreateMultipleClientComponent } from "./shared/clients/create-multiple-client/create-multiple-client.component"; import { SelectionModel } from "@angular/cdk/collections"; import { ManageClientComponent } from "./shared/clients/manage-client/manage-client.component"; import { debounceTime } from 'rxjs/operators'; import { Subject } from 'rxjs'; import { ConfigService } from '@services/config.service'; +import { GlobalStatusComponent } from '../global-status/global-status.component'; enum NodeType { OrganizationalUnit = 'organizational-unit', diff --git a/ogWebconsole/src/app/layout/header/header.component.html b/ogWebconsole/src/app/layout/header/header.component.html index b91ef5e..d70bb71 100644 --- a/ogWebconsole/src/app/layout/header/header.component.html +++ b/ogWebconsole/src/app/layout/header/header.component.html @@ -9,36 +9,39 @@