refs #1558. Add client/subnet new UX modal
testing/ogGui-multibranch/pipeline/head There was a failure building this commit Details

deb-pkg
Manuel Aranda Rosales 2025-02-27 11:05:26 +01:00
parent bae2069661
commit b29a3f58f1
20 changed files with 243 additions and 156 deletions

View File

@ -27,6 +27,14 @@
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="fill" class="full-width">
<mat-label>Vista tarjetas</mat-label>
<mat-select formControlName="groupsView" required>
<mat-option *ngFor="let option of views" [value]="option.value" >
{{ option.name }}
</mat-option>
</mat-select>
</mat-form-field>
</form>
</mat-dialog-content>
<mat-dialog-actions class="action-container">

View File

@ -24,6 +24,11 @@ export class AddUserModalComponent implements OnInit {
organizationalUnits: any[] = [];
userId: string | null = null;
protected views = [
{value: 'card', name: 'Tarjetas'},
{value: 'list', name: 'Listado'},
];
constructor(
public dialogRef: MatDialogRef<AddUserModalComponent>,
@Inject(MAT_DIALOG_DATA) public data: any,
@ -36,6 +41,7 @@ export class AddUserModalComponent implements OnInit {
username: ['', Validators.required],
password: ['', Validators.required],
role: ['', Validators.required],
groupsView: ['card', Validators.required],
organizationalUnits: [[]]
});
}
@ -55,15 +61,14 @@ export class AddUserModalComponent implements OnInit {
load(): void {
this.dataService.getUser(this.data).subscribe({
next: (response) => {
console.log(response);
const organizationalUnitIds = response.allowedOrganizationalUnits.map((unit: any) => unit['@id']);
// Patch the values to the form
this.userForm.patchValue({
username: response.username,
role: response.userGroups[0]['@id'],
organizationalUnits: organizationalUnitIds
role: response.userGroups.length > 0 ? response.userGroups[0]['@id'] : null,
organizationalUnits: organizationalUnitIds,
groupsView: response.groupsView
});
this.userId = response['@id'];
@ -85,7 +90,8 @@ export class AddUserModalComponent implements OnInit {
allowedOrganizationalUnits: this.userForm.value.organizationalUnit,
password: this.userForm.value.password,
enabled: true,
userGroups: [this.userForm.value.role ]
userGroups: [this.userForm.value.role ],
groupsView: this.userForm.value.groupsView
};
if (this.userId) {

View File

@ -32,6 +32,11 @@ export class UsersComponent implements OnInit {
header: 'Nombre de Usuario',
cell: (user: any) => `${user.username}`
},
{
columnDef: 'groupsView',
header: 'Vista de Grupos',
cell: (user: any) => `${user.groupsView}`
},
{
columnDef: 'allowedOrganizationalUnits',
header: 'Unidades Organizacionales Permitidas',

View File

@ -27,3 +27,16 @@ mat-dialog-actions {
gap: 1em;
padding: 1.5em;
}
.clients-grid {
display: grid;
grid-template-columns: repeat(3, 1fr); /* 3 columnas */
gap: 5px; /* Espaciado entre elementos */
}
.checkbox-group label {
font-weight: bold;
display: block;
margin-bottom: 10px;
}

View File

@ -1,3 +1,5 @@
<app-loading [isLoading]="loading"></app-loading>
<h2 mat-dialog-title>Añade clientes a {{data.subnetName}}</h2>
<mat-dialog-content>
@ -10,7 +12,12 @@
<div class="checkbox-group">
<label>Clientes</label>
<div *ngIf="clients.length > 0">
<button class="action-button" (click)="toggleSelectAll()" [disabled]="clients.length === 0">
{{ allSelected ? 'Deseleccionar todos' : 'Seleccionar todos' }}
</button>
<div *ngIf="clients.length > 0" class="clients-grid">
<mat-checkbox *ngFor="let client of clients"
(change)="toggleClientSelection(client.uuid)"
[checked]="selectedClients.includes(client.uuid)">

View File

@ -18,6 +18,7 @@ export class AddClientsToSubnetComponent implements OnInit {
loading: boolean = true;
unitControl = new FormControl();
childUnitControl = new FormControl();
allSelected: boolean = false;
constructor(
private http: HttpClient,
@ -43,7 +44,7 @@ export class AddClientsToSubnetComponent implements OnInit {
}
loadChildUnits(event: any) {
this.http.get<any>(`${this.baseUrl}/clients?organizationalUnit.id=${event.value.id}`).subscribe(
this.http.get<any>(`${this.baseUrl}/clients?organizationalUnit.id=${event.value.id}&exists[subnet]=false`).subscribe(
response => {
this.clients = response['hydra:member'];
},
@ -51,37 +52,49 @@ export class AddClientsToSubnetComponent implements OnInit {
);
}
toggleClientSelection(clientId: string): void {
const index = this.selectedClients.indexOf(clientId);
if (index >= 0) {
this.selectedClients.splice(index, 1);
} else {
this.selectedClients.push(clientId);
}
}
save() {
this.loading = true;
const postData = { clients: this.selectedClients.map(clientId => `/clients/${clientId}`) };
this.http.post(`${this.baseUrl}/og-dhcp/server/${this.data.subnetUuid}/post-host`, postData).subscribe(
(response: any) => {
this.dialog.open(OperationResultDialogComponent, {
width: '600px',
width: '800px',
data: {
success: response.success || [],
errors: response.errors || []
}
});
this.loading = false;
this.dialogRef.close(this.selectedClients);
},
error => {
console.error(`Error al asignar el cliente:`, error);
this.toastService.error(`Error al asignar el cliente: ${error.error['hydra:description']}`);
}
);
}
toggleSelectAll() {
if (this.allSelected) {
this.selectedClients = [];
} else {
this.selectedClients = this.clients.map(client => client.uuid);
}
this.allSelected = !this.allSelected;
}
toggleClientSelection(uuid: string) {
const index = this.selectedClients.indexOf(uuid);
if (index === -1) {
this.selectedClients.push(uuid);
} else {
this.selectedClients.splice(index, 1);
}
this.allSelected = this.selectedClients.length === this.clients.length;
}
close() {
this.dialogRef.close();
}

View File

@ -39,4 +39,11 @@ form {
justify-content: flex-end;
gap: 1em;
padding: 1.5em;
}
}
.step-title {
font-family: 'Roboto', sans-serif;
color: #3f51b5;
margin: 40px 0 15px 0;
display: block;
}

View File

@ -1,68 +1,38 @@
<h2 mat-dialog-title>{{ isEditMode ? 'Editar' : 'Añadir' }} subred</h2>
<mat-dialog-content>
<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>
<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>
<!-- Parámetros Avanzados -->
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>Parámetros avanzados</mat-panel-title>
</mat-expansion-panel-header>
<mat-form-field appearance="fill" class="full-width">
<mat-label>Next Server</mat-label>
<input matInput [(ngModel)]="nextServer" placeholder="Next Server">
</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">
</mat-form-field>
<mat-form-field appearance="fill" class="full-width">
<mat-label>Router</mat-label>
<input matInput [(ngModel)]="router" placeholder="Router">
</mat-form-field>
</mat-expansion-panel>
</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-divider></mat-divider>
<span class="step-title">Parámetros avanzados</span>
<mat-form-field appearance="fill" class="full-width">
<mat-label>Next Server</mat-label>
<input matInput [(ngModel)]="nextServer" placeholder="Next Server">
</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">
</mat-form-field>
<mat-form-field appearance="fill" class="full-width">
<mat-label>Router</mat-label>
<input matInput [(ngModel)]="router" placeholder="Router">
</mat-form-field>
</div>
</mat-dialog-content>
<mat-dialog-actions class="action-container">
<button class="ordinary-button" (click)="onNoClick()">Cancelar</button>
<button class="submit-button" (click)="save()" cdkFocusInitial>Guardar</button>
</mat-dialog-actions>
</mat-dialog-actions>

View File

@ -18,9 +18,7 @@ export class CreateSubnetComponent implements OnInit {
nextServer: string = '';
bootFileName: string = '';
router: string = '';
syncronized: boolean = false;
serverId: number = 0;
clients: any[] = [];
isEditMode: boolean = false;
constructor(
@ -46,9 +44,7 @@ export class CreateSubnetComponent implements OnInit {
this.nextServer = this.data.nextServer;
this.bootFileName = this.data.bootFileName;
this.router = this.data.router;
this.syncronized = this.data.syncronized;
this.serverId = this.data.serverId;
this.clients = this.data.clients
}
onNoClick(): void {
@ -69,12 +65,10 @@ export class CreateSubnetComponent implements OnInit {
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']);
}
});
@ -82,35 +76,13 @@ export class CreateSubnetComponent implements OnInit {
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']);
}
});
}})
}
}

View File

@ -1,3 +1,5 @@
<app-loading [isLoading]="loading"></app-loading>
<div class="header-container">
<button mat-icon-button color="primary" (click)="iniciarTour()">
<mat-icon>help</mat-icon>
@ -36,13 +38,6 @@
<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" joyrideStep="searchBootFileStep"
text="Busca subredes según el nombre del archivo de arranque.">
<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>
<app-loading [isLoading]="loading"></app-loading>

View File

@ -35,7 +35,7 @@ export interface Subnet {
templateUrl: './og-dhcp-subnets.component.html',
styleUrls: ['./og-dhcp-subnets.component.css']
})
export class OgDhcpSubnetsComponent {
export class OgDhcpSubnetsComponent implements OnInit {
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
displayedColumns: string[] = ['id', 'name', 'netmask', 'ipAddress', 'synchronized', 'serverId', 'clients', 'actions'];
dataSource = new MatTableDataSource<Subnet>([]);
@ -79,7 +79,7 @@ export class OgDhcpSubnetsComponent {
this.length = response['hydra:totalItems'];
},
error: error => {
console.error('Error al cargar plantillas PXE:', error);
this.toastService.error(error.error['hydra:description']);
}
});
@ -94,7 +94,6 @@ export class OgDhcpSubnetsComponent {
this.toastService.success('Sincronización con componente DHCP exitosa');
this.loadSubnets()
}, error => {
console.error('Error al sincronizar', error);
this.toastService.error('Error al sincronizar');
});
}
@ -214,7 +213,7 @@ export class OgDhcpSubnetsComponent {
height: '100vh',
maxWidth: '100vw',
maxHeight: '100vh',
data: { subnetId: subnet.id, subnetName: subnet.name }
data: { subnetId: subnet.id, subnetName: subnet.name, subnetUuid: subnet.uuid }
});
dialogRef.afterClosed().subscribe(result => {
@ -224,7 +223,7 @@ export class OgDhcpSubnetsComponent {
addClientsToSubnet(subnet: Subnet) {
const dialogRef = this.dialog.open(AddClientsToSubnetComponent, {
width: '600px',
width: '800px',
data: { subnetUuid: subnet.uuid, subnetName: subnet.name }
});

View File

@ -1,14 +1,34 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import {MAT_DIALOG_DATA } from '@angular/material/dialog';
import { OperationResultDialogComponent } from './operation-result-dialog.component';
import {ShowClientsComponent} from "../show-clients/show-clients.component";
import {MatExpansionModule} from "@angular/material/expansion";
import {MatIconModule} from "@angular/material/icon";
import {MatDividerModule} from "@angular/material/divider";
import {MatFormFieldModule} from "@angular/material/form-field";
import {MatSelectModule} from "@angular/material/select";
import {MatPaginatorModule} from "@angular/material/paginator";
import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
import {FormsModule} from "@angular/forms";
import {MatInputModule} from "@angular/material/input";
import {MatDialog, MatDialogModule, MatDialogRef} from "@angular/material/dialog";
import {MatTableModule} from "@angular/material/table";
import {TranslateModule} from "@ngx-translate/core";
import {JoyrideModule} from "ngx-joyride";
import {HttpClient} from "@angular/common/http";
import {ToastrService} from "ngx-toastr";
import {LoadingComponent} from "../../../shared/loading/loading.component";
describe('OperationResultDialogComponent', () => {
let component: OperationResultDialogComponent;
let fixture: ComponentFixture<OperationResultDialogComponent>;
let component: ShowClientsComponent;
let fixture: ComponentFixture<ShowClientsComponent>;
let mockDialog: jasmine.SpyObj<MatDialog>;
let mockHttpClient: jasmine.SpyObj<HttpClient>;
let mockToastrService: jasmine.SpyObj<ToastrService>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [OperationResultDialogComponent],
declarations: [OperationResultDialogComponent, LoadingComponent],
imports: [MatDialogModule],
providers: [
{ provide: MatDialogRef, useValue: {} },
@ -17,7 +37,36 @@ describe('OperationResultDialogComponent', () => {
})
.compileComponents();
fixture = TestBed.createComponent(OperationResultDialogComponent);
await TestBed.configureTestingModule({
declarations: [ShowClientsComponent],
imports: [
MatExpansionModule,
MatIconModule,
MatDividerModule,
MatFormFieldModule,
MatSelectModule,
MatPaginatorModule,
BrowserAnimationsModule,
FormsModule,
MatInputModule,
MatDialogModule,
MatTableModule,
TranslateModule.forRoot(),
JoyrideModule.forRoot(),
],
providers: [
{ provide: MatDialog, useValue: mockDialog },
{ provide: HttpClient, useValue: mockHttpClient },
{ provide: ToastrService, useValue: mockToastrService },
{
provide: MatDialogRef,
useValue: {}
},
],
})
.compileComponents();
fixture = TestBed.createComponent(ShowClientsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
@ -25,4 +74,4 @@ describe('OperationResultDialogComponent', () => {
it('should create', () => {
expect(component).toBeTruthy();
});
});
});

View File

@ -7,13 +7,6 @@ import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
template: `
<h2 mat-dialog-title>Resultado de la operación</h2>
<mat-dialog-content>
<div class="success-box" *ngIf="data.success.length > 0">
<h3>Éxitos</h3>
<ul>
<li *ngFor="let success of data.success">{{ success.client }} </li>
</ul>
</div>
<div class="error-box" *ngIf="data.errors.length > 0">
<h3>Errores</h3>
<ul>
@ -22,6 +15,12 @@ import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
</li>
</ul>
</div>
<div class="success-box" *ngIf="data.success.length > 0">
<h3>Éxitos</h3>
<ul>
<li *ngFor="let success of data.success">{{ success.client }} </li>
</ul>
</div>
</mat-dialog-content>
<mat-dialog-actions align="end">
<button mat-button color="primary" (click)="close()">Cerrar</button>

View File

@ -40,19 +40,6 @@ form {
gap: 1em;
padding: 1.5em;
}
.header-container {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 10px;
border-bottom: 1px solid #ddd;
}
.header-container-title {
flex-grow: 1;
text-align: left;
margin-left: 1em;
}
.lists-container {
padding: 16px;
@ -68,7 +55,12 @@ form {
}
.search-string {
flex: 2;
flex: 1;
padding: 5px;
}
.search-select {
flex: 1;
padding: 5px;
}

View File

@ -1,6 +1,6 @@
<app-loading [isLoading]="loading"></app-loading>
<h2 mat-dialog-title>Buscar clientes en {{data.subnetName}}</h2>
<h2 mat-dialog-title>Gestionar clientes en {{data.subnetName}}</h2>
<mat-dialog-content>
<div class="search-container">
@ -38,6 +38,17 @@
</button>
<mat-hint i18n="@@searchHint">Pulsar 'enter' para buscar</mat-hint>
</mat-form-field>
<mat-form-field class="form-field search-select" >
<mat-label>Estados</mat-label>
<mat-select [(ngModel)]="filters['status']" (selectionChange)="loadData()">
<mat-option *ngFor="let option of status" [value]="option.value" >
{{ option.name }}
</mat-option>
</mat-select>
<button *ngIf="filters['status']" mat-icon-button matSuffix aria-label="Clear tree search" (click)="filters['status'] = ''; loadData()">
<mat-icon>close</mat-icon>
</button>
</mat-form-field>
</div>
<app-loading [isLoading]="loading"></app-loading>
@ -54,12 +65,25 @@
{{ client.ogLive?.date | date }}
</ng-container>
<ng-container *ngIf="column.columnDef !== 'status' && column.columnDef !== 'ogLive'">
<ng-container *ngIf="column.columnDef === 'organizationalUnit'">
{{ client.organizationalUnit?.path }}
</ng-container>
<ng-container *ngIf="column.columnDef !== 'status' && column.columnDef !== 'ogLive' && column.columnDef !== 'organizationalUnit'">
{{ column.cell(client) }}
</ng-container>
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef i18n="@@columnActions" style="text-align: center;">Acciones</th>
<td mat-cell *matCellDef="let client" style="text-align: center;">
<button mat-icon-button color="warn" (click)="deleteClient(client)">
<mat-icon i18n="@@deleteElementTooltip">delete</mat-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
@ -70,7 +94,6 @@
(page)="onPageChange($event)">
</mat-paginator>
</div>
</mat-dialog-content>
<mat-dialog-actions class="action-container">

View File

@ -29,8 +29,6 @@ describe('ShowClientsComponent', () => {
mockDialog = jasmine.createSpyObj('MatDialog', ['open']);
mockHttpClient = jasmine.createSpyObj('HttpClient', ['get', 'post', 'put', 'delete']);
mockToastrService = jasmine.createSpyObj('ToastrService', ['success', 'error']);
mockHttpClient.get.and.returnValue(of({ 'hydra:member': [], 'hydra:totalItems': 0 }));
mockHttpClient.post.and.returnValue(of({}));
await TestBed.configureTestingModule({
declarations: [ShowClientsComponent, LoadingComponent],
@ -67,4 +65,4 @@ describe('ShowClientsComponent', () => {
it('should create', () => {
expect(component).toBeTruthy();
});
});
});

View File

@ -1,10 +1,10 @@
import { Component, Inject, OnInit } from '@angular/core';
import { ToastrService } from "ngx-toastr";
import { HttpClient } from "@angular/common/http";
import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from "@angular/material/dialog";
import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from "@angular/material/dialog";
import { MatTableDataSource } from "@angular/material/table";
import { Subnet } from "../og-dhcp-subnets.component";
import { Client } from "../../groups/model/model";
import {DeleteModalComponent} from "../../../shared/delete_modal/delete-modal/delete-modal.component";
@Component({
selector: 'app-show-clients',
@ -21,16 +21,27 @@ export class ShowClientsComponent implements OnInit {
loading: boolean = false;
filters: { [key: string]: string } = {};
protected status = [
{value: 'off', name: 'Apagado'},
{value: 'initializing', name: 'Inicializando'},
{value: 'og-live', name: 'Og Live'},
{value: 'linux', name: 'Linux'},
{value: 'linux-session', name: 'Linux Session'},
{value: 'windows', name: 'Windows'},
{value: 'mac', name: 'Mac'},
];
columns = [
{ columnDef: 'id', header: 'ID', cell: (client: Client) => client.id },
{ columnDef: 'status', header: 'Estado', cell: (client: Client) => client.status },
{ columnDef: 'name', header: 'Name', cell: (client: Client) => client.name },
{ columnDef: 'ip', header: 'Ip', cell: (client: Client) => client.ip },
{ columnDef: 'mac', header: 'Mac', cell: (client: Client) => client.mac },
{ columnDef: 'organizationalUnit', header: 'Ruta', cell: (client: Client) => client.organizationalUnit },
{ columnDef: 'ogLive', header: 'OgLive', cell: (client: Client) => client.ogLive?.date },
];
displayedColumns: string[] = ['id', 'status', 'name', 'ip', 'mac', 'ogLive'];
displayedColumns: string[] = ['id', 'status', 'name', 'ip', 'mac', 'organizationalUnit', 'ogLive', 'actions'];
constructor(
private toastService: ToastrService,
@ -61,6 +72,26 @@ export class ShowClientsComponent implements OnInit {
console.log(this.dataSource.data)
}
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.data.subnetUuid}/delete-host/${client.uuid}`, {}).subscribe({
next: () => {
this.toastService.success('Cliente eliminado exitosamente de la red');
this.loadData()
},
error: (error) => {
this.toastService.error(error.error['hydra:description']);
}
});
}})
}
onNoClick(): void {
this.dialogRef.close();
}

View File

@ -45,4 +45,4 @@
</button>
</mat-menu>
</div>
</mat-toolbar>
</mat-toolbar>

View File

@ -46,5 +46,5 @@ export class HeaderComponent implements OnInit {
width: '400px',
});
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 778 B