refs #614. Integration DHCP
parent
b78be472e1
commit
d0b6da5616
|
@ -0,0 +1,14 @@
|
|||
FROM node:22.1.0
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN npm install -g npm@latest
|
||||
|
||||
RUN npm install -g @angular/cli@^12.0.0
|
||||
|
||||
COPY . /app
|
||||
RUN npm install
|
||||
|
||||
EXPOSE 4200
|
||||
|
||||
CMD ["ng", "serve", "--host", "0.0.0.0", "--disable-host-check"]
|
|
@ -20,6 +20,7 @@ import { CommandsComponent } from './components/commands/main-commands/commands.
|
|||
import { CommandsGroupsComponent } from './components/commands/commands-groups/commands-groups.component';
|
||||
import { CommandsTaskComponent } from './components/commands/commands-task/commands-task.component';
|
||||
import { TaskLogsComponent } from './components/commands/commands-task/task-logs/task-logs.component';
|
||||
import { StatusComponent } from "./components/ogdhcp/og-dhcp-subnets/status/status.component";
|
||||
const routes: Routes = [
|
||||
{ path: '', redirectTo: 'auth/login', pathMatch: 'full' },
|
||||
{
|
||||
|
@ -36,7 +37,8 @@ const routes: Routes = [
|
|||
{ path: 'pxe-boot-file', component: PxeBootFilesComponent },
|
||||
{ path: 'ogboot-status', component: OgbootStatusComponent },
|
||||
{ path: 'dhcp', component: OgdhcpComponent },
|
||||
{ path: 'dhcp-subnets', component: OgDhcpSubnetsComponent },
|
||||
{ path: 'subnets', component: OgDhcpSubnetsComponent },
|
||||
{ path: 'ogdhcp-status', component: StatusComponent },
|
||||
{ path: 'commands', component: CommandsComponent },
|
||||
{ path: 'commands-groups', component: CommandsGroupsComponent },
|
||||
{ path: 'commands-task', component: CommandsTaskComponent },
|
||||
|
|
|
@ -100,6 +100,8 @@ import { ClientTabViewComponent } from './components/groups/components/client-ta
|
|||
import { AdvancedSearchComponent } from './components/groups/components/advanced-search/advanced-search.component';
|
||||
import { TaskLogsComponent } from './components/commands/commands-task/task-logs/task-logs.component';
|
||||
import { OrganizationalUnitTabViewComponent } from './components/groups/components/organizational-unit-tab-view/organizational-unit-tab-view.component';
|
||||
import { ServerInfoDialogComponent } from './components/ogdhcp/og-dhcp-subnets/server-info-dialog/server-info-dialog.component';
|
||||
import { StatusComponent } from './components/ogdhcp/og-dhcp-subnets/status/status.component';
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
|
@ -156,7 +158,9 @@ import { OrganizationalUnitTabViewComponent } from './components/groups/componen
|
|||
ClientTabViewComponent,
|
||||
AdvancedSearchComponent,
|
||||
TaskLogsComponent,
|
||||
OrganizationalUnitTabViewComponent
|
||||
OrganizationalUnitTabViewComponent,
|
||||
ServerInfoDialogComponent,
|
||||
StatusComponent
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
imports: [BrowserModule,
|
||||
|
|
|
@ -58,6 +58,6 @@
|
|||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</mat-dialog-content>
|
||||
<mat-dialog-actions>
|
||||
<mat-dialog-actions align="end">
|
||||
<button mat-button mat-dialog-close (click)="onNoClick()" i18n="@@close-button">Cerrar</button>
|
||||
</mat-dialog-actions>
|
||||
|
|
|
@ -26,12 +26,12 @@ export class ClientViewComponent {
|
|||
networkData = [
|
||||
{property: 'Menú', value: this.data.client.menu ? this.data.client.menu.description : ''},
|
||||
{property: 'Perfil hardware', value: this.data.client.hardwareProfile ? this.data.client.hardwareProfile.description : ''},
|
||||
{property: 'Subred', value: this.data.client.subnet},
|
||||
{property: 'OGlive', value: ''},
|
||||
{property: 'Autoexec', value: ''},
|
||||
{property: 'Repositorio', value: ''},
|
||||
{property: 'Validacion', value: ''},
|
||||
{property: 'Página login', value: ''},
|
||||
{property: 'Página validacion', value: ''},
|
||||
{property: 'Fecha de creación', value: this.data.client.createdAt},
|
||||
{property: 'Creado por', value: this.data.client.createdBy}
|
||||
];
|
||||
|
|
|
@ -2,15 +2,12 @@
|
|||
<mat-expansion-panel hideToggle>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title> Sincronización ogBoot </mat-panel-title>
|
||||
<mat-panel-description>
|
||||
<mat-icon [style.color]="getIcon().color">{{ getIcon().name }}</mat-icon>
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
<p *ngIf="alertMessage">Oglives creados en servidor ogBoot: {{ alertMessage }}</p>
|
||||
<p *ngIf="alertMessage">Oglives creados en servidor ogCore (base de datos): {{ length }}</p>
|
||||
|
||||
<div class="example-button-row">
|
||||
<button mat-flat-button color="primary" (click)="syncOgCore()"> Sincronizar OgCore</button>
|
||||
<button mat-flat-button color="primary" (click)="syncOgBoot()"> Sincronizar OgCore</button>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
||||
|
|
|
@ -199,15 +199,7 @@ export class ImagesComponent implements OnInit {
|
|||
});
|
||||
}
|
||||
|
||||
getIcon(): { name: string, color: string } {
|
||||
if (this.alertMessage) {
|
||||
return { name: 'check_circle', color: 'green' };
|
||||
} else {
|
||||
return { name: 'cancel', color: 'red' };
|
||||
}
|
||||
}
|
||||
|
||||
syncOgCore(): void {
|
||||
syncOgBoot(): void {
|
||||
this.http.post(`${this.apiUrl}/sync`, {})
|
||||
.subscribe(response => {
|
||||
this.toastService.success('Sincronización completada');
|
||||
|
|
|
@ -10,33 +10,33 @@
|
|||
}.dashboard {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
|
||||
.disk-usage-container {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
|
||||
.disk-usage {
|
||||
flex: 2;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
|
||||
.services-status {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
|
||||
.services-status ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
.services-status li {
|
||||
margin: 5px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
.status-led {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
|
@ -44,29 +44,29 @@
|
|||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
|
||||
.status-led.active {
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
|
||||
.status-led.inactive {
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
|
||||
.installed-oglives {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
|
||||
th, td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
|
||||
th {
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
@ -77,13 +77,13 @@
|
|||
gap: 10px; /* Espacio entre botones */
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.btn:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
|
||||
.btn:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,26 @@
|
|||
<h2 mat-dialog-title>Añade clientes a a {{data.subnetName}}</h2>
|
||||
<h2 mat-dialog-title>Añade clientes a {{data.subnetName}}</h2>
|
||||
|
||||
<mat-dialog-content>
|
||||
<div *ngIf="loading" class="loading-container">
|
||||
<mat-spinner></mat-spinner>
|
||||
<p>Cargando clientes...</p>
|
||||
</div>
|
||||
<mat-form-field appearance="fill" *ngIf="!loading" style="width: 100%;">
|
||||
<mat-label>Añadir clientes</mat-label>
|
||||
<mat-select [(value)]="selectedClients" multiple>
|
||||
<mat-option *ngFor="let client of clients" [value]="client">
|
||||
{{ client.name }} (IP: {{ client.ip }}, MAC: {{ client.mac }})
|
||||
<mat-form-field appearance="fill" class="search-select">
|
||||
<input type="text" matInput [formControl]="clientControl" [matAutocomplete]="clientAuto" placeholder="Seleccione un cliente">
|
||||
<mat-autocomplete #clientAuto="matAutocomplete" [displayWith]="displayFnClient" (optionSelected)="onOptionClientSelected($event.option.value)">
|
||||
<mat-option *ngFor="let client of filteredClients | async" [value]="client">
|
||||
{{ client.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-autocomplete>
|
||||
</mat-form-field>
|
||||
|
||||
<div *ngIf="selectedClients.length > 0">
|
||||
<h3>Clientes seleccionados:</h3>
|
||||
<ul>
|
||||
<li *ngFor="let client of selectedClients">
|
||||
{{ client.name }}
|
||||
<button mat-icon-button color="warn" (click)="removeClient(client)">
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</mat-dialog-content>
|
||||
|
||||
<mat-dialog-actions>
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
import { Component, OnInit, Inject } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import {Observable, startWith} from "rxjs";
|
||||
import {map} from "rxjs/operators";
|
||||
import {FormControl} from "@angular/forms";
|
||||
import {ToastrService} from "ngx-toastr";
|
||||
|
||||
@Component({
|
||||
selector: 'app-add-clients-to-subnet',
|
||||
|
@ -12,46 +16,87 @@ export class AddClientsToSubnetComponent implements OnInit {
|
|||
clients: any[] = [];
|
||||
selectedClients: any[] = [];
|
||||
loading: boolean = true;
|
||||
filters: { [key: string]: string } = {};
|
||||
filteredClients!: Observable<any[]>;
|
||||
clientControl = new FormControl();
|
||||
|
||||
constructor(
|
||||
private http: HttpClient,
|
||||
public dialogRef: MatDialogRef<AddClientsToSubnetComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: { subnetUuid: string, subnetName: string }
|
||||
private toastService: ToastrService,
|
||||
@Inject(MAT_DIALOG_DATA) public data: { subnetUuid: string, subnetName: string }
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
console.log('Selected subnet UUID:', this.data);
|
||||
this.loading = true;
|
||||
|
||||
this.http.get<any>(`${this.baseUrl}/clients?page=1&itemsPerPage=30`).subscribe(
|
||||
this.loadClients();
|
||||
|
||||
this.filteredClients = this.clientControl.valueChanges.pipe(
|
||||
startWith(''),
|
||||
map(value => (typeof value === 'string' ? value : value?.name)),
|
||||
map(name => (name ? this._filterClients(name) : this.clients.slice()))
|
||||
);
|
||||
}
|
||||
|
||||
loadClients() {
|
||||
this.http.get<any>( `${this.baseUrl}/clients?&page=1&itemsPerPage=10000&exists[subnet]=false`).subscribe(
|
||||
response => {
|
||||
this.clients = response['hydra:member'];
|
||||
this.loading = false;
|
||||
},
|
||||
error => {
|
||||
console.error('Error fetching clients:', error);
|
||||
console.error('Error fetching parent units:', error);
|
||||
this.loading = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
save() {
|
||||
const postData = {
|
||||
clients: JSON.stringify(this.selectedClients.map(client => client.uuid))
|
||||
};
|
||||
this.selectedClients.forEach(client => {
|
||||
const postData = {
|
||||
client: client['@id']
|
||||
};
|
||||
|
||||
this.http.post(`${this.baseUrl}/og-dhcp/server/${this.data.subnetUuid}/post-host`, postData).subscribe(
|
||||
response => {
|
||||
console.log('Clients assigned successfully:', response);
|
||||
this.dialogRef.close(this.selectedClients);
|
||||
},
|
||||
error => {
|
||||
console.error('Error assigning clients:', error);
|
||||
}
|
||||
);
|
||||
this.http.post(`${this.baseUrl}/og-dhcp/server/${this.data.subnetUuid}/post-host`, postData).subscribe(
|
||||
response => {
|
||||
this.toastService.success(`Cliente ${client.name} asignado correctamente`);
|
||||
},
|
||||
error => {
|
||||
console.error(`Error al asignar el cliente ${client.name}:`, error);
|
||||
this.toastService.error(`Error al asignar el cliente ${client.name}: ${error.error['hydra:description']}`);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
this.dialogRef.close(this.selectedClients);
|
||||
}
|
||||
|
||||
close() {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
removeClient(client: any) {
|
||||
const index = this.selectedClients.indexOf(client);
|
||||
if (index >= 0) {
|
||||
this.selectedClients.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private _filterClients(name: string): any[] {
|
||||
const filterValue = name.toLowerCase();
|
||||
return this.clients.filter(client => client.name.toLowerCase().includes(filterValue));
|
||||
}
|
||||
|
||||
displayFnClient(client: any): string {
|
||||
return client && client.name ? client.name : '';
|
||||
}
|
||||
|
||||
onOptionClientSelected(client: any) {
|
||||
if (!this.selectedClients.includes(client)) {
|
||||
this.selectedClients.push(client);
|
||||
}
|
||||
this.clientControl.setValue('');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,36 @@
|
|||
.full-width {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
form{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
form{
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.spacing-container {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.list-item-content {
|
||||
display: flex;
|
||||
align-items: flex-start; /* Alinea el contenido al inicio */
|
||||
justify-content: space-between; /* Espacio entre los textos y los íconos */
|
||||
width: 100%; /* Asegúrate de que el contenido ocupe todo el ancho */
|
||||
}
|
||||
|
||||
.text-content {
|
||||
flex-grow: 1;
|
||||
margin-right: 16px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.icon-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.right-icon {
|
||||
margin-left: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
padding: 20px;
|
||||
}
|
|
@ -1,27 +1,56 @@
|
|||
<h2 mat-dialog-title>Añadir configuración de red</h2>
|
||||
<h2 mat-dialog-title>{{ isEditMode ? 'Editar' : 'Añadir' }} subred</h2>
|
||||
|
||||
<mat-dialog-content>
|
||||
<mat-form-field appearance="fill" class="full-width">
|
||||
<mat-label>Nombre</mat-label>
|
||||
<input matInput [(ngModel)]="name" placeholder="Nombre de la subred" required>
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill" class="full-width">
|
||||
<mat-label>Netmask</mat-label>
|
||||
<input matInput [(ngModel)]="netmask" placeholder="Netmask" required>
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill" class="full-width">
|
||||
<mat-label>Dirección IP</mat-label>
|
||||
<input matInput [(ngModel)]="ipAddress" placeholder="Dirección IP" required>
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill" class="full-width">
|
||||
<mat-label>Next Server</mat-label>
|
||||
<input matInput [(ngModel)]="nextServer" placeholder="Next Server" required>
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill" class="full-width">
|
||||
<mat-label>Boot File Name</mat-label>
|
||||
<input matInput [(ngModel)]="bootFileName" placeholder="Boot File Name" required>
|
||||
</mat-form-field>
|
||||
<mat-tab-group>
|
||||
<mat-tab label="Subred">
|
||||
<div class="spacing-container">
|
||||
<mat-form-field appearance="fill" class="full-width">
|
||||
<mat-label>Nombre</mat-label>
|
||||
<input matInput [(ngModel)]="name" placeholder="Nombre de la subred" required>
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill" class="full-width">
|
||||
<mat-label>Netmask</mat-label>
|
||||
<input matInput [(ngModel)]="netmask" placeholder="Netmask" required>
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill" class="full-width">
|
||||
<mat-label>Dirección IP</mat-label>
|
||||
<input matInput [(ngModel)]="ipAddress" placeholder="Dirección IP" required>
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill" class="full-width">
|
||||
<mat-label>Next Server</mat-label>
|
||||
<input matInput [(ngModel)]="nextServer" placeholder="Next Server" required>
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill" class="full-width">
|
||||
<mat-label>Boot File Name</mat-label>
|
||||
<input matInput [(ngModel)]="bootFileName" placeholder="Boot File Name" required>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</mat-tab>
|
||||
|
||||
<mat-tab *ngIf="isEditMode" label="Clientes">
|
||||
<mat-list>
|
||||
<ng-container *ngFor="let client of clients">
|
||||
<mat-list-item >
|
||||
<div class="list-item-content">
|
||||
<mat-icon matListItemIcon>computer</mat-icon>
|
||||
<div class="text-content">
|
||||
<div matListItemTitle>{{ client.name }}</div>
|
||||
<div matListItemLine>{{ client.mac }}</div>
|
||||
</div>
|
||||
<div class="icon-container">
|
||||
<button mat-icon-button color="warn" class="right-icon" (click)="deleteClient(client)">
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</mat-list-item>
|
||||
</ng-container>
|
||||
</mat-list>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</mat-dialog-content>
|
||||
|
||||
<mat-dialog-actions align="end">
|
||||
<button mat-button (click)="onNoClick()">Cancelar</button>
|
||||
<button mat-button (click)="addNetworkConfig()" cdkFocusInitial>Añadir</button>
|
||||
<button mat-button (click)="addNetworkConfig()" cdkFocusInitial>Guardar</button>
|
||||
</mat-dialog-actions>
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { HttpClient } from '@angular/common/http';
|
||||
import { Component, Inject, OnInit } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material/dialog';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import {DeleteModalComponent} from "../../../../shared/delete_modal/delete-modal/delete-modal.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-create-subnet',
|
||||
|
@ -10,21 +11,42 @@ import { ToastrService } from 'ngx-toastr';
|
|||
})
|
||||
export class CreateSubnetComponent implements OnInit {
|
||||
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
|
||||
subnetId: string | null = null;
|
||||
name: string = '';
|
||||
netmask: string = '';
|
||||
ipAddress: string = '';
|
||||
nextServer: string = '';
|
||||
bootFileName: string = '';
|
||||
syncronized: boolean = false;
|
||||
serverId: number = 0;
|
||||
clients: any[] = [];
|
||||
isEditMode: boolean = false;
|
||||
|
||||
constructor(
|
||||
private toastService: ToastrService,
|
||||
private http: HttpClient,
|
||||
public dialogRef: MatDialogRef<CreateSubnetComponent>,
|
||||
public dialog: MatDialog,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
if (this.data) {
|
||||
this.loadData();
|
||||
this.isEditMode = true;
|
||||
}
|
||||
}
|
||||
|
||||
loadData() {
|
||||
this.subnetId = this.data.uuid;
|
||||
this.name = this.data.name;
|
||||
this.netmask = this.data.netmask;
|
||||
this.ipAddress = this.data.ipAddress;
|
||||
this.nextServer = this.data.nextServer;
|
||||
this.bootFileName = this.data.bootFileName;
|
||||
this.syncronized = this.data.syncronized;
|
||||
this.serverId = this.data.serverId;
|
||||
this.clients = this.data.clients
|
||||
}
|
||||
|
||||
onNoClick(): void {
|
||||
|
@ -40,17 +62,52 @@ export class CreateSubnetComponent implements OnInit {
|
|||
bootFileName: this.bootFileName
|
||||
};
|
||||
|
||||
this.http.post(`${this.baseUrl}/subnets`, payload)
|
||||
.subscribe({
|
||||
next: (response) => {
|
||||
console.log('Success:', response);
|
||||
this.toastService.success('Configuración de red añadida exitosamente');
|
||||
this.dialogRef.close();
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Error:', error);
|
||||
this.toastService.error(error.error['hydra:description']);
|
||||
}
|
||||
});
|
||||
if (!this.data){
|
||||
this.http.post(`${this.baseUrl}/subnets`, payload)
|
||||
.subscribe({
|
||||
next: (response) => {
|
||||
console.log('Success:', response);
|
||||
this.toastService.success('Configuración de red añadida exitosamente');
|
||||
this.dialogRef.close();
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Error:', error);
|
||||
this.toastService.error(error.error['hydra:description']);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.http.patch(`${this.baseUrl}/subnets/${this.subnetId}`, payload)
|
||||
.subscribe({
|
||||
next: (response) => {
|
||||
console.log('Success:', response);
|
||||
this.toastService.success('Configuración de red actualizada exitosamente');
|
||||
this.dialogRef.close();
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Error:', error);
|
||||
this.toastService.error(error.error['hydra:description']);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
deleteClient(client: any): void {
|
||||
const dialogRef = this.dialog.open(DeleteModalComponent, {
|
||||
width: '300px',
|
||||
data: { name: client.name }
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
if (result) {
|
||||
this.http.delete(`${this.baseUrl}/og-dhcp/server/${this.subnetId}/delete-host/${client.uuid}`, {}).subscribe({
|
||||
next: () => {
|
||||
this.toastService.success('Cliente eliminado exitosamente');
|
||||
this.dialogRef.close();
|
||||
},
|
||||
error: (error) => {
|
||||
this.toastService.error(error.error['hydra:description']);
|
||||
}
|
||||
});
|
||||
}})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
<mat-accordion class="example-headers-align">
|
||||
<mat-expansion-panel hideToggle>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title> Información de Subnets </mat-panel-title>
|
||||
<mat-panel-description>
|
||||
<mat-icon [style.color]="getIcon().color">{{ getIcon().name }}</mat-icon>
|
||||
</mat-panel-description>
|
||||
<mat-panel-title> Información en servidor ogDHCP </mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<p *ngIf="alertMessage">Subnets sincronizadas: {{ alertMessage }}</p>
|
||||
<p *ngIf="alertMessage">Número de subnets en base de datos: {{ length }}</p>
|
||||
|
||||
<div class="example-button-row">
|
||||
<button mat-flat-button color="primary" (click)="syncSubnets()"> Sincronizar Subnets</button>
|
||||
<button mat-flat-button color="primary" (click)="syncSubnets()"> Sincronizar base de datos</button>
|
||||
</div>
|
||||
<div class="example-button-row">
|
||||
<button mat-flat-button color="accent" (click)="openSubnetInfoDialog()">Ver Información</button>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
||||
|
@ -25,7 +22,7 @@
|
|||
<mat-divider class="divider"></mat-divider>
|
||||
<div class="search-container">
|
||||
<mat-form-field appearance="fill" class="search-string">
|
||||
<mat-label i18n="@@searchLabel">Buscar nombre de imagen</mat-label>
|
||||
<mat-label i18n="@@searchLabel">Buscar nombre de la subred</mat-label>
|
||||
<input matInput placeholder="Búsqueda" [(ngModel)]="filters['name']" i18n-placeholder="@@searchPlaceholder">
|
||||
<mat-icon matSuffix>search</mat-icon>
|
||||
<mat-hint i18n="@@searchHint">Pulsar 'enter' para buscar</mat-hint>
|
||||
|
@ -42,13 +39,35 @@
|
|||
<mat-icon matSuffix>search</mat-icon>
|
||||
<mat-hint i18n="@@searchHint">Pulsar 'enter' para buscar</mat-hint>
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill" class="search-string">
|
||||
<mat-label i18n="@@searchLabel">Buscar Boot file name</mat-label>
|
||||
<input matInput placeholder="Búsqueda" [(ngModel)]="filters['bootFileName']" i18n-placeholder="@@searchPlaceholder">
|
||||
<mat-icon matSuffix>search</mat-icon>
|
||||
<mat-hint i18n="@@searchHint">Pulsar 'enter' para buscar</mat-hint>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<mat-divider class="divider"></mat-divider>
|
||||
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
|
||||
<ng-container *ngFor="let column of columns" [matColumnDef]="column.columnDef">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ column.header }} </th>
|
||||
<td mat-cell *matCellDef="let subnet">
|
||||
<ng-container >
|
||||
|
||||
<ng-container *ngIf="column.columnDef === 'synchronized'">
|
||||
<mat-icon [color]="subnet[column.columnDef] ? 'primary' : 'warn'">
|
||||
{{ subnet[column.columnDef] ? 'check_circle' : 'cancel' }}
|
||||
</mat-icon>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="column.columnDef === 'clients'">
|
||||
<button mat-button [matMenuTriggerFor]="menu">Ver clientes</button>
|
||||
<mat-menu #menu="matMenu">
|
||||
<button mat-menu-item *ngFor="let client of subnet.clients">
|
||||
{{ client.name }}
|
||||
</button>
|
||||
</mat-menu>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="column.columnDef !== 'synchronized' && column.columnDef !== 'clients'">
|
||||
{{ column.cell(subnet) }}
|
||||
</ng-container>
|
||||
</td>
|
||||
|
@ -59,10 +78,15 @@
|
|||
<td mat-cell *matCellDef="let subnet" style="text-align: center;">
|
||||
<button mat-icon-button color="primary" (click)="editSubnet(subnet)" i18n="@@editSubnet">
|
||||
<mat-icon>edit</mat-icon></button>
|
||||
<button mat-icon-button color="warn" (click)="deleteSubnet(subnet)"><mat-icon>delete</mat-icon></button>
|
||||
<button mat-icon-button (click)="addClientsToSubnet(subnet)">
|
||||
<mat-icon>computer</mat-icon>
|
||||
<button mat-icon-button color="warn" (click)="toggleAction(subnet, 'delete')"><mat-icon>delete</mat-icon></button>
|
||||
<button mat-icon-button [matMenuTriggerFor]="menu">
|
||||
<mat-icon>menu</mat-icon>
|
||||
</button>
|
||||
<mat-menu #menu="matMenu">
|
||||
<button mat-menu-item (click)="toggleAction(subnet, 'post')">Crear en og-dhcp</button>
|
||||
<button mat-menu-item (click)="addClientsToSubnet(subnet)">Añadir cliente</button>
|
||||
<button mat-menu-item (click)="toggleAction(subnet, 'put')">Actualizar datos en og-dhcp</button>
|
||||
</mat-menu>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import { HttpClient } from '@angular/common/http';
|
|||
import { DeleteModalComponent } from '../../../shared/delete_modal/delete-modal/delete-modal.component';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { AddClientsToSubnetComponent } from './add-clients-to-subnet/add-clients-to-subnet.component';
|
||||
import {ServerInfoDialogComponent} from "./server-info-dialog/server-info-dialog.component";
|
||||
|
||||
export interface Subnet {
|
||||
'@id': string;
|
||||
|
@ -16,6 +17,9 @@ export interface Subnet {
|
|||
ipAddress: string;
|
||||
nextServer: string;
|
||||
bootFileName: string;
|
||||
synchronized: boolean;
|
||||
serverId: number;
|
||||
clients: [];
|
||||
createdAt: string;
|
||||
createdBy: string;
|
||||
uuid: string;
|
||||
|
@ -29,7 +33,7 @@ export interface Subnet {
|
|||
})
|
||||
export class OgDhcpSubnetsComponent {
|
||||
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
|
||||
displayedColumns: string[] = ['id', 'name', 'netmask', 'ipAddress', 'nextServer', 'bootFileName', 'actions'];
|
||||
displayedColumns: string[] = ['id', 'name', 'netmask', 'ipAddress', 'nextServer', 'bootFileName', 'synchronized', 'serverId', 'clients', 'actions'];
|
||||
dataSource = new MatTableDataSource<Subnet>([]);
|
||||
length = 0;
|
||||
itemsPerPage: number = 10;
|
||||
|
@ -47,16 +51,22 @@ export class OgDhcpSubnetsComponent {
|
|||
{ columnDef: 'ipAddress', header: 'IP Address', cell: (subnet: Subnet) => subnet.ipAddress },
|
||||
{ columnDef: 'nextServer', header: 'Next Server', cell: (subnet: Subnet) => subnet.nextServer },
|
||||
{ columnDef: 'bootFileName', header: 'Boot File Name', cell: (subnet: Subnet) => subnet.bootFileName },
|
||||
{ columnDef: 'synchronized', header: 'Sincronizado', cell: (subnet: Subnet) => `${subnet.synchronized}`},
|
||||
{ columnDef: 'serverId', header: 'IP Servidor DHCP', cell: (subnet: Subnet) => subnet.serverId },
|
||||
{ columnDef: 'clients', header: 'Lista de clientes', cell: (subnet: Subnet) => `${subnet.clients}`},
|
||||
];
|
||||
|
||||
private apiUrl = `${this.baseUrl}/subnets`;
|
||||
|
||||
constructor(public dialog: MatDialog, private http: HttpClient, private toastService: ToastrService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.loadSubnets();
|
||||
this.loadAlert()
|
||||
}
|
||||
|
||||
loadSubnets() {
|
||||
this.http.get<any>(`${this.baseUrl}/subnets?page=1&itemsPerPage=${this.itemsPerPage}`).subscribe({
|
||||
this.http.get<any>(`${this.baseUrl}/subnets?page=${this.page + 1}&itemsPerPage=${this.itemsPerPage}`).subscribe({
|
||||
next: (response) => {
|
||||
this.dataSource.data = response['hydra:member'];
|
||||
this.length = response['hydra:totalItems'];
|
||||
|
@ -72,75 +82,129 @@ export class OgDhcpSubnetsComponent {
|
|||
}
|
||||
|
||||
syncSubnets() {
|
||||
console.log('Sincronizando subnets...');
|
||||
this.http.post(`${this.apiUrl}/sync`, {})
|
||||
.subscribe(response => {
|
||||
this.toastService.success('Sincronización completada');
|
||||
this.loadSubnets()
|
||||
}, error => {
|
||||
console.error('Error al sincronizar', error);
|
||||
this.toastService.error('Error al sincronizar');
|
||||
});
|
||||
}
|
||||
|
||||
toggleAction(subnet: any, action:string): void {
|
||||
switch (action) {
|
||||
case 'get':
|
||||
this.http.post(`${this.baseUrl}/og-dhcp/server/${subnet.uuid}/get`, {}).subscribe({
|
||||
next: () => {
|
||||
this.toastService.success('Subred sincronizada con servidor');
|
||||
this.loadSubnets()
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Error al crear subred en servidor', error);
|
||||
this.toastService.error(error.error['hydra:description']);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'post':
|
||||
this.http.post(`${this.baseUrl}/og-dhcp/server/${subnet.uuid}/post`, {}).subscribe({
|
||||
next: () => {
|
||||
this.toastService.success('Petición de instalación enviada');
|
||||
this.loadSubnets()
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Error al crear subred en servidor', error);
|
||||
this.toastService.error(error.error['hydra:description']);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'put':
|
||||
this.http.put(`${this.baseUrl}/og-dhcp/server/${subnet.uuid}/put`, {}).subscribe({
|
||||
next: () => {
|
||||
this.toastService.success('Petición de actualizacion enviada');
|
||||
this.loadSubnets();
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Error al actualizar la subred en el servidor', error);
|
||||
this.toastService.error(error.error['hydra:description']);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'delete':
|
||||
const dialogRef = this.dialog.open(DeleteModalComponent, {
|
||||
width: '300px',
|
||||
data: { name: subnet.name }
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
if (result) {
|
||||
this.http.delete(`${this.baseUrl}/og-dhcp/server/${subnet.uuid}/delete`, {}).subscribe({
|
||||
next: () => {
|
||||
this.toastService.success('Subred eliminada exitosamente');
|
||||
this.loadSubnets();
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Error al eliminar la subred', error);
|
||||
this.toastService.error(error.error['hydra:description']);
|
||||
}
|
||||
});
|
||||
}})
|
||||
break;
|
||||
default:
|
||||
console.error('Acción no soportada:', action);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
addSubnet() {
|
||||
console.log('Añadiendo nueva subnet...');
|
||||
const dialogRef = this.dialog.open(CreateSubnetComponent, {
|
||||
width: '400px'
|
||||
width: '600px'
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
console.log('The dialog was closed');
|
||||
this.loadSubnets()
|
||||
});
|
||||
}
|
||||
|
||||
editSubnet(subnet: Subnet) {
|
||||
console.log('Editando subnet:', subnet);
|
||||
const dialogRef = this.dialog.open(CreateSubnetComponent, {
|
||||
width: '400px',
|
||||
data: { subnet }
|
||||
width: '600px',
|
||||
data: subnet
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
console.log('The dialog was closed');
|
||||
this.loadSubnets()
|
||||
});
|
||||
}
|
||||
|
||||
deleteSubnet(subnet: Subnet): void {
|
||||
console.log(subnet);
|
||||
const dialogRef = this.dialog.open(DeleteModalComponent, {
|
||||
width: '300px',
|
||||
data: { name: subnet.name }
|
||||
});
|
||||
loadAlert() {
|
||||
this.http.get(`${this.baseUrl}/og-dhcp/server/get-collection`)
|
||||
.subscribe(response => {
|
||||
// @ts-ignore
|
||||
this.alertMessage = response.message
|
||||
}, error => {
|
||||
console.error('Error al cargar la información del alert', error);
|
||||
});
|
||||
}
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
if (result) {
|
||||
const apiUrl = `${this.baseUrl}${subnet['@id']}`;
|
||||
|
||||
this.http.delete(apiUrl).subscribe({
|
||||
next: () => {
|
||||
console.log('Subnet deleted successfully');
|
||||
this.dataSource.data = this.dataSource.data.filter(s => s !== subnet);
|
||||
this.length = this.dataSource.data.length;
|
||||
this.toastService.success('Subnet deleted successfully');
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Error deleting subnet:', error);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log('Subnet deletion cancelled');
|
||||
openSubnetInfoDialog() {
|
||||
this.loadAlert()
|
||||
this.dialog.open(ServerInfoDialogComponent, {
|
||||
width: '600px',
|
||||
data: {
|
||||
alertMessage: this.alertMessage,
|
||||
length: this.length
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
updateSubnet() {
|
||||
console.log('Update Subnet action selected');
|
||||
}
|
||||
|
||||
addClientsToSubnet(subnet: Subnet) {
|
||||
|
||||
const dialogRef = this.dialog.open(AddClientsToSubnetComponent, {
|
||||
width: '600px',
|
||||
data: { subnetUuid: subnet.uuid, subnetName: subnet.name }
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
console.log('The dialog was closed');
|
||||
this.loadSubnets();
|
||||
});
|
||||
}
|
||||
|
@ -148,13 +212,6 @@ export class OgDhcpSubnetsComponent {
|
|||
onPageChange(event: any) {
|
||||
this.page = event.pageIndex;
|
||||
this.itemsPerPage = event.pageSize;
|
||||
}
|
||||
|
||||
getIcon(): { name: string, color: string } {
|
||||
if (this.alertMessage) {
|
||||
return { name: 'check_circle', color: 'green' };
|
||||
} else {
|
||||
return { name: 'cancel', color: 'red' };
|
||||
}
|
||||
this.loadSubnets();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<h2 mat-dialog-title>Información de Subnets</h2>
|
||||
<mat-dialog-content>
|
||||
<pre>{{ data | json }}</pre>
|
||||
</mat-dialog-content>
|
||||
<mat-dialog-actions align="end">
|
||||
<button mat-button mat-dialog-close>Cerrar</button>
|
||||
</mat-dialog-actions>
|
|
@ -0,0 +1,23 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ServerInfoDialogComponent } from './server-info-dialog.component';
|
||||
|
||||
describe('ServerInfoDialogComponent', () => {
|
||||
let component: ServerInfoDialogComponent;
|
||||
let fixture: ComponentFixture<ServerInfoDialogComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ServerInfoDialogComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ServerInfoDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,12 @@
|
|||
import {Component, Inject} from '@angular/core';
|
||||
import {MAT_DIALOG_DATA} from "@angular/material/dialog";
|
||||
|
||||
@Component({
|
||||
selector: 'app-server-info-dialog',
|
||||
templateUrl: './server-info-dialog.component.html',
|
||||
styleUrl: './server-info-dialog.component.css'
|
||||
})
|
||||
export class ServerInfoDialogComponent {
|
||||
constructor(@Inject(MAT_DIALOG_DATA) public data: any) {}
|
||||
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
|
||||
.disk-usage-info{
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-left: 15px;
|
||||
}.dashboard {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.disk-usage-container {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.disk-usage {
|
||||
flex: 2;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.services-status {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.services-status ul {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.services-status li {
|
||||
justify-content: left;
|
||||
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;
|
||||
}
|
||||
|
||||
.installed-oglives {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
th, td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
||||
.button-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px; /* Espacio entre botones */
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.btn:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.btn:last-child {
|
||||
margin-right: 0;
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
<div class="dashboard">
|
||||
<h2>OgBoot server Status</h2>
|
||||
|
||||
<div class="disk-usage-container">
|
||||
<div class="disk-usage">
|
||||
<h3>Uso de disco</h3>
|
||||
<ngx-charts-pie-chart
|
||||
[view]="view"
|
||||
[scheme]="colorScheme"
|
||||
[results]="diskUsageChartData"
|
||||
[gradient]="gradient"
|
||||
[doughnut]="isDoughnut"
|
||||
[labels]="showLabels"
|
||||
[legend]="showLegend">
|
||||
</ngx-charts-pie-chart>
|
||||
<div class="disk-usage-info">
|
||||
<p>Total: {{ diskUsage.total }}</p>
|
||||
<p>Ocupado: {{ diskUsage.used }}</p>
|
||||
<p>Disponible: {{ diskUsage.available }}</p>
|
||||
<p>Libre: {{ diskUsage.percentage }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="services-status">
|
||||
<h3>Servicios</h3>
|
||||
<ul>
|
||||
<li *ngFor="let service of getServices()">
|
||||
<span
|
||||
class="status-led"
|
||||
[ngClass]="{ 'active': service.status === 'active', 'inactive': service.status !== 'active' }"
|
||||
></span>
|
||||
{{ service.name }}: {{ service.status }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="installed-oglives">
|
||||
<h3>Subredes</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Boot file name</th>
|
||||
<th>Next server</th>
|
||||
<th>Ip</th>
|
||||
<th>Ordenadores</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let subnet of subnets">
|
||||
<td>{{ subnet.id }}</td>
|
||||
<td>{{ subnet['boot-file-name'] }}</td>
|
||||
<td>{{ subnet['next-server'] }}</td>
|
||||
<td>{{ subnet.subnet }}</td>
|
||||
<td>{{ subnet.reservations.length }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,23 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { StatusComponent } from './status.component';
|
||||
|
||||
describe('StatusComponent', () => {
|
||||
let component: StatusComponent;
|
||||
let fixture: ComponentFixture<StatusComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [StatusComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(StatusComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,58 @@
|
|||
import { Component } from '@angular/core';
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
|
||||
@Component({
|
||||
selector: 'app-status',
|
||||
templateUrl: './status.component.html',
|
||||
styleUrl: './status.component.css'
|
||||
})
|
||||
export class StatusComponent {
|
||||
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
|
||||
diskUsage: any = {};
|
||||
servicesStatus: any = {};
|
||||
subnets: any[] = [];
|
||||
diskUsageChartData: any[] = [];
|
||||
|
||||
view: [number, number] = [1100, 500];
|
||||
|
||||
gradient: boolean = true;
|
||||
showLegend: boolean = true;
|
||||
showLabels: boolean = true;
|
||||
isDoughnut: boolean = true;
|
||||
colorScheme: any = {
|
||||
domain: ['#FF6384', '#3f51b5']
|
||||
};
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.loadStatus();
|
||||
}
|
||||
loadStatus(): void {
|
||||
this.http.get<any>(`${this.baseUrl}/og-dhcp/status`).subscribe(data => {
|
||||
this.diskUsage = data.message.disk_usage;
|
||||
this.servicesStatus = data.message.services_status;
|
||||
this.subnets = data.message.subnets;
|
||||
|
||||
this.diskUsageChartData = [
|
||||
{
|
||||
name: 'Usado',
|
||||
value: parseFloat(this.diskUsage.used)
|
||||
},
|
||||
{
|
||||
name: 'Disponible',
|
||||
value: parseFloat(this.diskUsage.available)
|
||||
}
|
||||
];
|
||||
}, error => {
|
||||
console.error('Error fetching status', error);
|
||||
});
|
||||
}
|
||||
|
||||
getServices(): { name: string, status: string }[] {
|
||||
return Object.keys(this.servicesStatus).map(key => ({
|
||||
name: key,
|
||||
status: this.servicesStatus[key]
|
||||
}));
|
||||
}
|
||||
}
|
|
@ -60,7 +60,13 @@
|
|||
|
||||
<!-- Submenu items ogdhcp -->
|
||||
<mat-nav-list *ngIf="showOgDhcpSub" style="padding-left: 20px;">
|
||||
<mat-list-item routerLink="/dhcp-subnets">
|
||||
<mat-list-item routerLink="/ogdhcp-status">
|
||||
<span class="entry">
|
||||
<mat-icon class="icon">analytics</mat-icon>
|
||||
<span i18n="@@gallery">Estado</span>
|
||||
</span>
|
||||
</mat-list-item>
|
||||
<mat-list-item routerLink="/subnets">
|
||||
<span class="entry">
|
||||
<mat-icon class="icon">lan</mat-icon>
|
||||
<span i18n="@@gallery">Subnets</span>
|
||||
|
@ -141,5 +147,5 @@
|
|||
</span>
|
||||
</mat-list-item>
|
||||
|
||||
|
||||
|
||||
</mat-nav-list>
|
||||
|
|
|
@ -16,11 +16,9 @@ export class SidebarComponent {
|
|||
showCommandSub: boolean = false;
|
||||
|
||||
toggleOgBootSub() {
|
||||
alert('El correcto funcionamiento de este componente está sujeto a la disponibilidad de la API de ogBoot');
|
||||
this.showOgBootSub = !this.showOgBootSub;
|
||||
}
|
||||
toggleOgDhcpSub() {
|
||||
alert('El correcto funcionamiento de este componente está sujeto a la disponibilidad de la API de ogDHCP');
|
||||
this.showOgDhcpSub = !this.showOgDhcpSub;
|
||||
}
|
||||
toggleCommandSub() {
|
||||
|
|
Loading…
Reference in New Issue