refs #1282. Adapted ogCore filter. Refactor unused and wrong code
parent
369e09ee86
commit
013536bc9e
|
@ -31,9 +31,11 @@
|
|||
<ng-container *ngIf="column.columnDef !== 'readOnly'">
|
||||
{{ column.cell(command) }}
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="column.columnDef === 'readOnly'">
|
||||
<mat-chip *ngIf="command.readOnly" class="mat-chip-readonly-true"><mat-icon style="color:white;">check</mat-icon></mat-chip>
|
||||
<mat-chip *ngIf="!command.readOnly" class="mat-chip-readonly-false"><mat-icon style="color:white;">close</mat-icon></mat-chip>
|
||||
<mat-icon [color]="command[column.columnDef] ? 'primary' : 'warn'">
|
||||
{{ command[column.columnDef] ? 'check_circle' : 'cancel' }}
|
||||
</mat-icon>
|
||||
</ng-container>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
@ -41,7 +43,6 @@
|
|||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef style="text-align: center;">{{ 'columnActions' | translate }}</th>
|
||||
<td mat-cell *matCellDef="let command" style="text-align: center;" joyrideStep="actionsStep" text="{{ 'actionsStepText' | translate }}">
|
||||
<button mat-icon-button color="info" (click)="executeCommand($event, command)"><mat-icon>play_arrow</mat-icon></button>
|
||||
<button mat-icon-button color="info" (click)="viewDetails($event, command)"><mat-icon>visibility</mat-icon></button>
|
||||
<button mat-icon-button color="primary" [disabled]="command.readOnly" (click)="editCommand($event, command)"><mat-icon>edit</mat-icon></button>
|
||||
<button mat-icon-button color="warn" [disabled]="command.readOnly" (click)="deleteCommand($event, command)"><mat-icon>delete</mat-icon></button>
|
||||
|
|
|
@ -50,7 +50,7 @@ export class CommandsComponent implements OnInit {
|
|||
displayedColumns = [...this.columns.map(column => column.columnDef), 'actions'];
|
||||
private apiUrl = `${this.baseUrl}/commands`;
|
||||
|
||||
constructor(private http: HttpClient, private dialog: MatDialog, private toastService: ToastrService,
|
||||
constructor(private http: HttpClient, private dialog: MatDialog, private toastService: ToastrService,
|
||||
private joyrideService: JoyrideService) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
|
@ -114,19 +114,6 @@ export class CommandsComponent implements OnInit {
|
|||
});
|
||||
}
|
||||
|
||||
executeCommand(event: MouseEvent, command: any): void {
|
||||
this.dialog.open(ExecuteCommandComponent, {
|
||||
width: '50%',
|
||||
data: { commandData: command }
|
||||
}).afterClosed().subscribe((result) => {
|
||||
if (result) {
|
||||
console.log('Comando ejecutado con éxito');
|
||||
} else {
|
||||
console.log('Ejecución de comando cancelada');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onPageChange(event: any): void {
|
||||
this.page = event.pageIndex;
|
||||
this.itemsPerPage = event.pageSize;
|
||||
|
@ -147,5 +134,5 @@ export class CommandsComponent implements OnInit {
|
|||
themeColor: '#3f51b5'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,40 +1,10 @@
|
|||
<h2 mat-dialog-title>{{ 'executeCommandTitle' | translate }}</h2>
|
||||
<button mat-icon-button color="primary" [matMenuTriggerFor]="commandMenu">
|
||||
<mat-icon>terminal</mat-icon>
|
||||
</button>
|
||||
|
||||
<mat-dialog-content class="form-container">
|
||||
<form [formGroup]="form" class="command-form">
|
||||
|
||||
<mat-form-field appearance="fill" class="full-width">
|
||||
<mat-label>{{ 'organizationalUnitLabel' | translate }}</mat-label>
|
||||
<mat-select formControlName="unit">
|
||||
<mat-option *ngFor="let unit of units" [value]="unit.uuid">{{ unit.name }}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-menu #commandMenu="matMenu">
|
||||
<button mat-menu-item [disabled]="command.disabled" *ngFor="let command of arrayCommands" (click)="onCommandSelect(command.slug)">
|
||||
{{ command.name }}
|
||||
</button>
|
||||
</mat-menu>
|
||||
|
||||
<mat-form-field appearance="fill" class="full-width">
|
||||
<mat-label>{{ 'subOrganizationalUnitLabel' | translate }}</mat-label>
|
||||
<mat-select formControlName="childUnit">
|
||||
<mat-option *ngFor="let child of childUnits" [value]="child.uuid">{{ child.name }}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<div class="checkbox-group">
|
||||
<label>{{ 'clientsLabel' | translate }}</label>
|
||||
<div *ngIf="clients.length > 0">
|
||||
<mat-checkbox *ngFor="let client of clients"
|
||||
(change)="toggleClientSelection(client.uuid)"
|
||||
[checked]="form.get('clientSelection')?.value.includes(client.uuid)">
|
||||
{{ client.name }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<div *ngIf="clients.length === 0">
|
||||
<p>{{ 'noClientsAvailable' | translate }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</mat-dialog-content>
|
||||
|
||||
<mat-dialog-actions align="end">
|
||||
<button mat-button (click)="closeModal()">{{ 'buttonCancel' | translate }}</button>
|
||||
<button mat-button (click)="executeCommand()" [disabled]="!form.get('clientSelection')?.value.length">{{ 'buttonExecute' | translate }}</button>
|
||||
</mat-dialog-actions>
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import { Component, Inject, OnInit } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import {Component, Inject, Input, OnInit} from '@angular/core';
|
||||
import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from '@angular/material/dialog';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import {Router} from "@angular/router";
|
||||
import {ToastrService} from "ngx-toastr";
|
||||
|
||||
@Component({
|
||||
selector: 'app-execute-command',
|
||||
|
@ -9,92 +11,129 @@ import { FormBuilder, FormGroup } from '@angular/forms';
|
|||
styleUrls: ['./execute-command.component.css']
|
||||
})
|
||||
export class ExecuteCommandComponent implements OnInit {
|
||||
form: FormGroup;
|
||||
units: any[] = [];
|
||||
childUnits: any[] = [];
|
||||
clients: any[] = [];
|
||||
selectedClients: any[] = [];
|
||||
@Input() clientData: any = {};
|
||||
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
|
||||
loading: boolean = true;
|
||||
|
||||
arrayCommands: any[] = [
|
||||
{name: 'Enceder', slug: 'power-on', disabled: false},
|
||||
{name: 'Apagar', slug: 'power-off', disabled: false},
|
||||
{name: 'Reiniciar', slug: 'reboot', disabled: false},
|
||||
{name: 'Iniciar Sesión', slug: 'login', disabled: true},
|
||||
{name: 'Crear Image', slug: 'create-image', disabled: false},
|
||||
{name: 'Deploy Image', slug: 'deploy-image', disabled: false},
|
||||
{name: 'Eliminar Imagen Cache', slug: 'delete-image-cache', disabled: true},
|
||||
{name: 'Particionar y Formatear', slug: 'partition', disabled: false},
|
||||
{name: 'Inventario Software', slug: 'software-inventory', disabled: true},
|
||||
{name: 'Inventario Hardware', slug: 'hardware-inventory', disabled: true},
|
||||
{name: 'Ejecutar script', slug: 'run-script', disabled: true},
|
||||
];
|
||||
|
||||
constructor(
|
||||
private dialogRef: MatDialogRef<ExecuteCommandComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||
private dialog: MatDialog,
|
||||
private http: HttpClient,
|
||||
private fb: FormBuilder
|
||||
private fb: FormBuilder,
|
||||
private router: Router,
|
||||
private toastService: ToastrService
|
||||
) {
|
||||
this.form = this.fb.group({
|
||||
unit: [null],
|
||||
childUnit: [null],
|
||||
clientSelection: [[]]
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.loadUnits();
|
||||
this.form.get('unit')?.valueChanges.subscribe(value => this.onUnitChange(value));
|
||||
this.form.get('childUnit')?.valueChanges.subscribe(value => this.onChildUnitChange(value));
|
||||
this.clientData = this.clientData || {};
|
||||
this.loadClient(this.clientData)
|
||||
}
|
||||
|
||||
loadUnits(): void {
|
||||
this.http.get<any>(`${this.baseUrl}/organizational-units?page=1&itemsPerPage=30`).subscribe(
|
||||
response => {
|
||||
this.units = response['hydra:member'].filter((unit: { type: string; }) => unit.type === 'organizational-unit');
|
||||
loadClient = (uuid: string) => {
|
||||
this.http.get<any>(`${this.baseUrl}${uuid}`).subscribe({
|
||||
next: data => {
|
||||
this.clientData = data;
|
||||
this.loading = false;
|
||||
},
|
||||
error => console.error('Error fetching organizational units:', error)
|
||||
error: error => {
|
||||
console.error('Error al obtener el cliente:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onCommandSelect(action: any): void {
|
||||
if (action === 'partition') {
|
||||
this.openPartitionAssistant();
|
||||
}
|
||||
|
||||
if (action === 'create-image') {
|
||||
this.openCreateImageAssistant();
|
||||
}
|
||||
|
||||
if (action === 'deploy-image') {
|
||||
this.openDeployImageAssistant();
|
||||
}
|
||||
|
||||
if (action === 'reboot') {
|
||||
this.rebootClient();
|
||||
}
|
||||
|
||||
if (action === 'power-off') {
|
||||
this.powerOffClient();
|
||||
}
|
||||
|
||||
if (action === 'power-on') {
|
||||
this.powerOnClient();
|
||||
}
|
||||
}
|
||||
|
||||
rebootClient(): void {
|
||||
this.http.post(`${this.baseUrl}/clients/server/${this.clientData.uuid}/reboot`, {}).subscribe(
|
||||
response => {
|
||||
this.toastService.success('Cliente actualizado correctamente');
|
||||
},
|
||||
error => {
|
||||
this.toastService.error('Error de conexión con el cliente');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
onUnitChange(unitId: string): void {
|
||||
const unit = this.units.find(unit => unit.uuid === unitId);
|
||||
this.childUnits = unit ? this.getAllChildren(unit) : [];
|
||||
this.clients = [];
|
||||
this.form.patchValue({ childUnit: null, clientSelection: [] });
|
||||
}
|
||||
|
||||
getAllChildren(unit: any): any[] {
|
||||
let allChildren = [];
|
||||
if (unit.children && unit.children.length > 0) {
|
||||
for (const child of unit.children) {
|
||||
allChildren.push(child);
|
||||
allChildren = allChildren.concat(this.getAllChildren(child));
|
||||
}
|
||||
}
|
||||
return allChildren;
|
||||
}
|
||||
|
||||
onChildUnitChange(childUnitId: string): void {
|
||||
const childUnit = this.childUnits.find(unit => unit.uuid === childUnitId);
|
||||
this.clients = childUnit && childUnit.clients ? childUnit.clients : [];
|
||||
this.form.patchValue({ clientSelection: [] });
|
||||
}
|
||||
|
||||
executeCommand(): void {
|
||||
powerOnClient(): void {
|
||||
const payload = {
|
||||
clients: ['/clients/'+this.form.get('clientSelection')?.value]
|
||||
};
|
||||
|
||||
this.http.post(`${this.baseUrl}/commands/${this.data.commandData.uuid}/execute`, payload)
|
||||
.subscribe({
|
||||
next: () => {
|
||||
console.log('Comando ejecutado con éxito');
|
||||
this.dialogRef.close(true);
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Error al ejecutar el comando:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
closeModal(): void {
|
||||
this.dialogRef.close(false);
|
||||
}
|
||||
|
||||
toggleClientSelection(clientId: string): void {
|
||||
const selectedClients = this.form.get('clientSelection')?.value;
|
||||
if (selectedClients.includes(clientId)) {
|
||||
this.form.get('clientSelection')?.setValue(selectedClients.filter((id: string) => id !== clientId));
|
||||
} else {
|
||||
this.form.get('clientSelection')?.setValue([...selectedClients, clientId]);
|
||||
client: this.clientData['@id']
|
||||
}
|
||||
|
||||
this.http.post(`${this.baseUrl}${this.clientData.repository['@id']}/wol`, payload).subscribe(
|
||||
response => {
|
||||
this.toastService.success('Cliente actualizado correctamente');
|
||||
},
|
||||
error => {
|
||||
this.toastService.error('Error de conexión con el cliente');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
powerOffClient(): void {
|
||||
this.http.post(`${this.baseUrl}/clients/server/${this.clientData.uuid}/power-off`, {}).subscribe(
|
||||
response => {
|
||||
this.toastService.success('Cliente actualizado correctamente');
|
||||
},
|
||||
error => {
|
||||
this.toastService.error('Error de conexión con el cliente');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
openPartitionAssistant(): void {
|
||||
this.router.navigate([`/clients/${this.clientData.uuid}/partition-assistant`]).then(r => {
|
||||
console.log('navigated', r);
|
||||
});
|
||||
}
|
||||
|
||||
openCreateImageAssistant(): void {
|
||||
this.router.navigate([`/clients/${this.clientData.uuid}/create-image`]).then(r => {
|
||||
console.log('navigated', r);
|
||||
});
|
||||
}
|
||||
|
||||
openDeployImageAssistant(): void {
|
||||
this.router.navigate([`/clients/${this.clientData.uuid}/deploy-image`]).then(r => {
|
||||
console.log('navigated', r);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -122,6 +122,7 @@ export class ClientMainViewComponent implements OnInit {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
updateGeneralData() {
|
||||
this.generalData = [
|
||||
{ property: 'Nombre', value: this.clientData?.name || '' },
|
||||
|
|
|
@ -187,7 +187,6 @@ export class DeployImageComponent {
|
|||
.subscribe({
|
||||
next: (response) => {
|
||||
this.toastService.success('Petición de despliegue enviada correctamente');
|
||||
this.router.navigate(['/commands-logs'])
|
||||
},
|
||||
error: (error) => {
|
||||
console.error('Error:', error);
|
||||
|
|
|
@ -166,10 +166,6 @@
|
|||
</button>
|
||||
</mat-menu>
|
||||
<mat-menu #menu="matMenu">
|
||||
<button *ngIf="selectedNode?.type === 'classroom'" mat-menu-item [matMenuTriggerFor]="commandMenu" (click)="fetchCommands()">
|
||||
<mat-icon>play_arrow</mat-icon>
|
||||
<span>{{ 'executeCommand' | translate }}</span>
|
||||
</button>
|
||||
<button mat-menu-item (click)="onShowDetailsClick($event, selectedNode)">
|
||||
<mat-icon matTooltip="{{ 'viewUnitTooltip' | translate }}" matTooltipHideDelay="0">visibility</mat-icon>
|
||||
<span>{{ 'viewUnitMenu' | translate }}</span>
|
||||
|
@ -227,9 +223,7 @@
|
|||
<button mat-icon-button color="primary" (click)="onShowClientDetail($event, client)">
|
||||
<mat-icon>visibility</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button color="primary">
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
<app-execute-command [clientData]="client['@id']"></app-execute-command>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -245,7 +239,6 @@
|
|||
[src]="'assets/images/ordenador_' + client.status + '.png'"
|
||||
alt="Client Icon"
|
||||
class="client-image" />
|
||||
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
|
@ -299,25 +292,14 @@
|
|||
<td mat-cell *matCellDef="let client"> {{ client.parentName }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions">
|
||||
<ng-container matColumnDef="actions" >
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{ 'actions' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let client">
|
||||
<button mat-icon-button [matMenuTriggerFor]="clientMenu">
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
<app-execute-command [clientData]="client['@id']"></app-execute-command>
|
||||
<mat-menu #clientMenu="matMenu">
|
||||
|
||||
<mat-menu restoreFocus=false #commandMenu="matMenu" xPosition="before">
|
||||
<button mat-menu-item *ngFor="let command of commands" (click)="executeClientCommand(command, client)">
|
||||
<span>{{ command.name }}</span>
|
||||
</button>
|
||||
</mat-menu>
|
||||
|
||||
<button mat-menu-item [matMenuTriggerFor]="commandMenu" (click)="fetchCommands()">
|
||||
<mat-icon>play_arrow</mat-icon>
|
||||
<span>{{ 'executeCommand' | translate }}</span>
|
||||
</button>
|
||||
|
||||
<button mat-menu-item (click)="onEditClick($event, client.type, client.uuid)">
|
||||
<mat-icon>edit</mat-icon>
|
||||
<span>{{ 'edit' | translate }}</span>
|
||||
|
|
|
@ -135,6 +135,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
private transformer = (node: TreeNode, level: number): FlatNode => ({
|
||||
id: node.id,
|
||||
name: node.name,
|
||||
type: node.type,
|
||||
level,
|
||||
|
@ -268,6 +269,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
|
|||
|
||||
private convertToTreeData(data: UnidadOrganizativa): TreeNode[] {
|
||||
const processNode = (node: UnidadOrganizativa): TreeNode => ({
|
||||
id: node.id,
|
||||
name: node.name,
|
||||
type: node.type,
|
||||
'@id': node['@id'],
|
||||
|
@ -279,34 +281,22 @@ export class GroupsComponent implements OnInit, OnDestroy {
|
|||
|
||||
|
||||
onNodeClick(node: TreeNode): void {
|
||||
console.log('Node clicked:', node);
|
||||
this.selectedNode = node;
|
||||
this.fetchClientsForNode(node);
|
||||
}
|
||||
|
||||
private fetchClientsForNode(node: TreeNode): void {
|
||||
if (node.hasClients && node['@id']) {
|
||||
this.subscriptions.add(
|
||||
this.http.get<{ clients: Client[] }>(`${this.baseUrl}${node['@id']}`).subscribe(
|
||||
(data) => {
|
||||
const clientsWithParentName = (data.clients || []).map(client => ({
|
||||
...client,
|
||||
parentName: node.name
|
||||
}));
|
||||
this.selectedClients.data = clientsWithParentName;
|
||||
this.selectedClients._updateChangeSubscription();
|
||||
if (this._paginator) {
|
||||
this._paginator.firstPage();
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
console.error('Error fetching clients:', error);
|
||||
}
|
||||
)
|
||||
);
|
||||
} else {
|
||||
this.selectedClients.data = [];
|
||||
this.selectedClients._updateChangeSubscription();
|
||||
}
|
||||
console.log('Node:', node);
|
||||
this.http.get<any>(`${this.baseUrl}/clients?organizationalUnit.id=${node.id}`).subscribe({
|
||||
next: (response) => {
|
||||
this.selectedClients.data = response['hydra:member'];
|
||||
this.loading = false;
|
||||
},
|
||||
error: () => {
|
||||
this.loading = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getNodeIcon(node: TreeNode): string {
|
||||
|
@ -357,7 +347,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
|
|||
.filter(node => this.treeControl.isExpanded(node))
|
||||
.map(node => this.extractUuid(node['@id']))
|
||||
: [];
|
||||
|
||||
|
||||
this.subscriptions.add(
|
||||
this.dataService.getOrganizationalUnits().subscribe(
|
||||
(data) => {
|
||||
|
@ -368,7 +358,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
|
|||
const treeData = this.convertToTreeData(updatedData);
|
||||
this.originalTreeData = treeData[0]?.children || [];
|
||||
this.treeDataSource.data = [...this.originalTreeData];
|
||||
|
||||
|
||||
setTimeout(() => {
|
||||
this.treeControl.dataNodes.forEach(node => {
|
||||
const nodeId = this.extractUuid(node['@id']);
|
||||
|
@ -384,7 +374,7 @@ export class GroupsComponent implements OnInit, OnDestroy {
|
|||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
onEditNode(event: MouseEvent, node: TreeNode | null): void {
|
||||
event.stopPropagation();
|
||||
|
@ -494,10 +484,6 @@ export class GroupsComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
}
|
||||
|
||||
executeClientCommand(command: Command, client: Client): void {
|
||||
this.toastr.success(`Ejecutando comando: ${command.name} en ${client.name}`);
|
||||
}
|
||||
|
||||
onShowClientDetail(event: MouseEvent, client: Client): void {
|
||||
event.stopPropagation();
|
||||
this.router.navigate(['clients', client.uuid], { state: { clientData: client } });
|
||||
|
@ -591,13 +577,13 @@ export class GroupsComponent implements OnInit, OnDestroy {
|
|||
this.toastr.success('Cliente actualizado correctamente');
|
||||
this.syncStatus = false;
|
||||
this.syncingClientId = null;
|
||||
this.onNodeClick(node);
|
||||
this.search()
|
||||
},
|
||||
() => {
|
||||
this.toastr.error('Error de conexión con el cliente');
|
||||
this.syncStatus = false;
|
||||
this.syncingClientId = null;
|
||||
this.onNodeClick(node);
|
||||
this.search()
|
||||
}
|
||||
)
|
||||
);
|
||||
|
|
|
@ -60,6 +60,7 @@ export interface ClientCollection {
|
|||
}
|
||||
|
||||
export interface TreeNode {
|
||||
id?: string
|
||||
name: string;
|
||||
type: string;
|
||||
'@id'?: string;
|
||||
|
@ -70,6 +71,7 @@ export interface TreeNode {
|
|||
}
|
||||
|
||||
export interface FlatNode {
|
||||
id?: string;
|
||||
name: string;
|
||||
type: string;
|
||||
level: number;
|
||||
|
|
Loading…
Reference in New Issue