diff --git a/ogWebconsole/src/app/app.module.ts b/ogWebconsole/src/app/app.module.ts
index 7a944c5..e2eb538 100644
--- a/ogWebconsole/src/app/app.module.ts
+++ b/ogWebconsole/src/app/app.module.ts
@@ -135,6 +135,7 @@ import { registerLocaleData } from '@angular/common';
import localeEs from '@angular/common/locales/es';
import { GlobalStatusComponent } from './components/global-status/global-status.component';
import { ShowImagesComponent } from './components/repositories/show-images/show-images.component';
+import { StatusTabComponent } from './components/global-status/status-tab/status-tab.component';
export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http, './locale/', '.json');
@@ -229,7 +230,8 @@ registerLocaleData(localeEs, 'es-ES');
OperationResultDialogComponent,
ConvertImageComponent,
GlobalStatusComponent,
- ShowImagesComponent
+ ShowImagesComponent,
+ StatusTabComponent
],
bootstrap: [AppComponent],
imports: [BrowserModule,
diff --git a/ogWebconsole/src/app/components/global-status/status-tab/status-tab.component.css b/ogWebconsole/src/app/components/global-status/status-tab/status-tab.component.css
new file mode 100644
index 0000000..0fccf20
--- /dev/null
+++ b/ogWebconsole/src/app/components/global-status/status-tab/status-tab.component.css
@@ -0,0 +1,72 @@
+.dashboard {
+ display: flex;
+ flex-direction: column;
+}
+
+.disk-usage-container {
+ display: flex;
+ flex-direction: column;
+}
+
+.disk-usage {
+ flex: 1;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+}
+
+.service-list {
+ margin-top: 0em;
+ margin-bottom: 0.5em;
+}
+
+.services-status {
+ display: flex;
+ flex-direction: column;
+}
+
+.services-status li {
+ margin: 5px 0;
+ display: flex;
+ align-items: center;
+}
+
+.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;
+}
+
+.disk-title {
+ margin-bottom: 0px;
+}
+
+.service-title {
+ margin-top: 0px;
+}
+
+table {
+ width: 100%;
+ border-collapse: collapse;
+}
+
+th,
+td {
+ border: 1px solid #ddd;
+ padding: 8px;
+}
+
+th {
+ background-color: #f4f4f4;
+}
\ No newline at end of file
diff --git a/ogWebconsole/src/app/components/global-status/status-tab/status-tab.component.html b/ogWebconsole/src/app/components/global-status/status-tab/status-tab.component.html
new file mode 100644
index 0000000..c94d266
--- /dev/null
+++ b/ogWebconsole/src/app/components/global-status/status-tab/status-tab.component.html
@@ -0,0 +1,56 @@
+
+
+
+
+
{{ 'diskUsageTitle' | translate }}
+
+
+
+
+
{{ 'totalLabel' | translate }}: {{ formatBytes(diskUsage.total) }}
+
+
{{ 'usedLabel' | translate }}: {{ formatBytes(diskUsage.used) }}
+
+
{{ 'availableLabel' | translate }}: {{ formatBytes(diskUsage.available)
+ }}
+
{{ 'freeLabel' | translate }}: {{ diskUsage.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 }} |
+
+
+
+
+
\ No newline at end of file
diff --git a/ogWebconsole/src/app/components/global-status/status-tab/status-tab.component.spec.ts b/ogWebconsole/src/app/components/global-status/status-tab/status-tab.component.spec.ts
new file mode 100644
index 0000000..c29ac03
--- /dev/null
+++ b/ogWebconsole/src/app/components/global-status/status-tab/status-tab.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 { ConfigService } from '@services/config.service';
+import { LoadingComponent } from 'src/app/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';
+import { StatusTabComponent } from './status-tab.component';
+
+describe('StatusTabComponent', () => {
+ let component: StatusTabComponent;
+ let fixture: ComponentFixture;
+
+ const mockConfigService = {
+ apiUrl: 'http://mock-api-url'
+ };
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [StatusTabComponent, LoadingComponent],
+ imports: [
+ HttpClientTestingModule,
+ ToastrModule.forRoot(),
+ MatDialogModule,
+ MatTabsModule,
+ TranslateModule.forRoot(),
+ NgxChartsModule,
+ BrowserAnimationsModule
+ ],
+ providers: [
+ { provide: ConfigService, useValue: mockConfigService }
+ ],
+ schemas: [NO_ERRORS_SCHEMA]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(StatusTabComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/ogWebconsole/src/app/components/global-status/status-tab/status-tab.component.ts b/ogWebconsole/src/app/components/global-status/status-tab/status-tab.component.ts
new file mode 100644
index 0000000..970cfa1
--- /dev/null
+++ b/ogWebconsole/src/app/components/global-status/status-tab/status-tab.component.ts
@@ -0,0 +1,43 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+ selector: 'app-status-tab',
+ templateUrl: './status-tab.component.html',
+ styleUrl: './status-tab.component.css'
+})
+export class StatusTabComponent {
+ @Input() loading: boolean = false;
+ @Input() diskUsage: any = {};
+ @Input() servicesStatus: any = {};
+ @Input() installedOgLives: any[] = [];
+ @Input() diskUsageChartData: any[] = [];
+ @Input() showLabels: boolean = true;
+ @Input() isDoughnut: boolean = true;
+ @Input() colorScheme: any = {
+ domain: ['#df200d', '#26a700']
+ };
+ @Input() view: [number, number] = [400, 220];
+
+ getServices(): { name: string, status: string }[] {
+ if (!this.servicesStatus) {
+ return [];
+ }
+ const services = Object.keys(this.servicesStatus).map(key => ({
+ name: key,
+ status: this.servicesStatus[key]
+ }))
+ return services;
+ }
+
+ 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';
+ }
+ }
+}