Refactor create-command component and commands component
parent
e852a7243f
commit
0b0ca83ac2
|
@ -54,7 +54,7 @@ import { MatExpansionModule } from '@angular/material/expansion';
|
|||
import { DragDropModule } from '@angular/cdk/drag-drop';
|
||||
import { ToastrModule } from 'ngx-toastr';
|
||||
import { ShowOrganizationalUnitComponent } from './components/groups/organizational-units/show-organizational-unit/show-organizational-unit.component';
|
||||
import {MatGridList, MatGridTile} from "@angular/material/grid-list";
|
||||
import { MatGridList, MatGridTile } from "@angular/material/grid-list";
|
||||
import { TreeViewComponent } from './components/groups/tree-view/tree-view.component';
|
||||
import {
|
||||
MatNestedTreeNode,
|
||||
|
@ -66,7 +66,7 @@ import {
|
|||
} from "@angular/material/tree";
|
||||
import { LegendComponent } from './components/groups/legend/legend.component';
|
||||
import { ClassroomViewDialogComponent } from './components/groups/classroom-view/classroom-view-modal';
|
||||
import {MatPaginator} from "@angular/material/paginator";
|
||||
import { MatPaginator } from "@angular/material/paginator";
|
||||
import { SaveFiltersDialogComponent } from './components/groups/save-filters-dialog/save-filters-dialog.component';
|
||||
import { AcctionsModalComponent } from './components/groups/acctions-modal/acctions-modal.component';
|
||||
import { ImagesComponent } from './components/ogboot/images/images.component';
|
||||
|
@ -75,7 +75,7 @@ import { InfoImageComponent } from './components/ogboot/images/info-image/info-i
|
|||
import { PxeComponent } from './components/ogboot/pxe/pxe.component';
|
||||
import { CreatePxeTemplateComponent } from './components/ogboot/pxe/create-pxeTemplate/create-pxe-template.component';
|
||||
import { PxeBootFilesComponent } from './components/ogboot/pxe-boot-files/pxe-boot-files.component';
|
||||
import {MatExpansionPanel, MatExpansionPanelDescription, MatExpansionPanelTitle} from "@angular/material/expansion";
|
||||
import { MatExpansionPanel, MatExpansionPanelDescription, MatExpansionPanelTitle } from "@angular/material/expansion";
|
||||
import { OgbootStatusComponent } from './components/ogboot/ogboot-status/ogboot-status.component';
|
||||
import { CreatePxeBootFileComponent } from './components/ogboot/pxe-boot-files/create-pxeBootFile/create-pxe-boot-file/create-pxe-boot-file.component';
|
||||
import { NgxChartsModule } from '@swimlane/ngx-charts';
|
||||
|
@ -86,6 +86,8 @@ import { AddClientsToSubnetComponent } from './components/ogdhcp/og-dhcp-subnets
|
|||
import { CommandsComponent } from './components/commands/commands.component';
|
||||
import { CommandDetailComponent } from './components/commands/command-detail/command-detail/command-detail.component';
|
||||
import { CreateCommandComponent } from './components/commands/create-command/create-command.component';
|
||||
import { MatDatepickerModule } from '@angular/material/datepicker';
|
||||
import { MatNativeDateModule } from '@angular/material/core';
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
|
@ -156,6 +158,8 @@ import { CreateCommandComponent } from './components/commands/create-command/cre
|
|||
MatSlideToggleModule, MatMenu, MatMenuTrigger, MatMenuItem, MatAutocomplete, MatChipListbox, MatChipOption, MatChipSet, MatChipsModule, MatChip, MatProgressSpinner, MatTabGroup, MatTab, MatTooltip,
|
||||
MatExpansionModule,
|
||||
NgxChartsModule,
|
||||
MatDatepickerModule,
|
||||
MatNativeDateModule,
|
||||
ToastrModule.forRoot(
|
||||
{
|
||||
timeOut: 5000,
|
||||
|
|
|
@ -1,81 +1,64 @@
|
|||
.modal-container {
|
||||
background-color: #fff;
|
||||
.header-container {
|
||||
background-color: #f8f9fa;
|
||||
padding: 20px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
width: calc(100% - 20px); /* Ajusta el ancho para dejar un margen */
|
||||
height: calc(100% - 20px); /* Ajusta la altura para dejar un margen */
|
||||
margin: 10px; /* Añade el margen para que no esté pegado a los bordes */
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
font-family: 'Roboto', sans-serif;
|
||||
box-sizing: border-box; /* Asegura que los bordes y el padding se incluyan en el tamaño */
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
.title {
|
||||
font-size: 1.5em;
|
||||
margin-bottom: 15px;
|
||||
color: #333;
|
||||
border-bottom: 2px solid #eee;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
flex-grow: 1;
|
||||
overflow-y: auto;
|
||||
padding: 10px; /* Añade espacio entre el contenido y los bordes del modal */
|
||||
box-sizing: border-box; /* Asegura que el padding esté dentro del ancho del modal */
|
||||
}
|
||||
|
||||
.modal-content p {
|
||||
margin: 10px 0;
|
||||
font-size: 1em;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.script-display {
|
||||
margin-top: 20px;
|
||||
background-color: #282c34;
|
||||
color: #ffffff;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
font-size: 0.9em;
|
||||
overflow: auto;
|
||||
color: #343a40;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.button-row {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 20px;
|
||||
padding: 10px; /* Añade espacio en el borde inferior */
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.button-row button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.primary-button {
|
||||
background-color: #007bff;
|
||||
color: #fff;
|
||||
border-radius: 4px;
|
||||
padding: 8px 16px;
|
||||
font-size: 1em;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.accent-button {
|
||||
background-color: #17a2b8;
|
||||
color: #fff;
|
||||
.button-row button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
.cancel-button {
|
||||
background-color: #dc3545;
|
||||
color: #fff;
|
||||
.table-container {
|
||||
padding: 20px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.primary-button:hover,
|
||||
.accent-button:hover,
|
||||
.cancel-button:hover {
|
||||
opacity: 0.9;
|
||||
.mat-elevation-z8 {
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
pre {
|
||||
margin: 0;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
.mat-header-cell {
|
||||
background-color: #e9ecef;
|
||||
color: #495057;
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.mat-cell {
|
||||
padding: 16px;
|
||||
color: #495057;
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
}
|
||||
|
||||
.mat-row:hover {
|
||||
background-color: #f1f1f1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mat-header-row {
|
||||
border-bottom: 2px solid #007bff;
|
||||
}
|
||||
|
|
|
@ -12,8 +12,42 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="additional-section" *ngIf="showClientSelect">
|
||||
<form [formGroup]="form">
|
||||
<h4>Selecciona los clientes:</h4>
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Clientes</mat-label>
|
||||
<mat-select formControlName="selectedClients" multiple (selectionChange)="onClientSelectionChange($event)">
|
||||
<mat-option *ngFor="let client of clients" [value]="client.id">
|
||||
{{ client.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
<mat-error *ngIf="form.get('selectedClients')?.invalid && form.get('selectedClients')?.touched">
|
||||
Debes seleccionar al menos un cliente.
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-checkbox formControlName="scheduleExecution" (change)="onScheduleChange($event)">
|
||||
Programar ejecución
|
||||
</mat-checkbox>
|
||||
<div *ngIf="showDatePicker" class="schedule-container">
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Fecha</mat-label>
|
||||
<input matInput [matDatepicker]="picker" formControlName="scheduleDate">
|
||||
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker></mat-datepicker>
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Hora</mat-label>
|
||||
<input matInput type="time" formControlName="scheduleTime">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="button-row">
|
||||
<button mat-button color="primary" class="primary-button" (click)="execute()">Ejecutar</button>
|
||||
<button mat-button color="primary" class="primary-button" [disabled]="false" (click)="execute()" >
|
||||
{{ showClientSelect ? 'Ejecutar' : 'Configurar ejecución' }}
|
||||
</button>
|
||||
<button mat-button color="accent" class="accent-button" (click)="edit()">Editar</button>
|
||||
<button mat-button class="cancel-button" (click)="cancel()">Cancelar</button>
|
||||
</div>
|
||||
|
|
|
@ -1,24 +1,70 @@
|
|||
import { Component, Inject } from '@angular/core';
|
||||
import { Component, Inject, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
|
||||
import { CreateCommandComponent } from '../../create-command/create-command.component';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
|
||||
@Component({
|
||||
selector: 'app-command-detail',
|
||||
templateUrl: './command-detail.component.html',
|
||||
styleUrls: ['./command-detail.component.css']
|
||||
})
|
||||
export class CommandDetailComponent {
|
||||
export class CommandDetailComponent implements OnInit {
|
||||
form!: FormGroup;
|
||||
clients: any[] = [];
|
||||
showClientSelect = false;
|
||||
showDatePicker = false;
|
||||
canExecute = false;
|
||||
|
||||
constructor(
|
||||
private fb: FormBuilder,
|
||||
private http: HttpClient,
|
||||
public dialogRef: MatDialogRef<CommandDetailComponent>,
|
||||
private dialog: MatDialog,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any // Recibe el comando desde el componente padre
|
||||
@Inject(MAT_DIALOG_DATA) public data: any
|
||||
) {}
|
||||
|
||||
// Funciones para los botones
|
||||
|
||||
ngOnInit(): void {
|
||||
this.form = this.fb.group({
|
||||
selectedClients: [[], Validators.required],
|
||||
scheduleExecution: [false],
|
||||
scheduleDate: [''],
|
||||
scheduleTime: ['']
|
||||
});
|
||||
|
||||
this.http.get<any>('http://127.0.0.1:8001/clients?page=1&itemsPerPage=30').subscribe(response => {
|
||||
this.clients = response['hydra:member'];
|
||||
});
|
||||
}
|
||||
|
||||
execute(): void {
|
||||
console.log('Ejecutar comando:', this.data);
|
||||
this.dialogRef.close(); // Cierra el modal después de ejecutar
|
||||
if (!this.showClientSelect) {
|
||||
this.showClientSelect = true;
|
||||
} else {
|
||||
if (this.form.get('selectedClients')?.value.length > 0) {
|
||||
console.log('Ejecutar comando con los siguientes clientes:', this.form.value.selectedClients);
|
||||
this.dialogRef.close();
|
||||
} else {
|
||||
this.form.get('selectedClients')?.markAsTouched();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onClientSelectionChange(event: any): void {
|
||||
this.canExecute = this.form.get('selectedClients')?.value.length > 0;
|
||||
}
|
||||
|
||||
onScheduleChange(event: any): void {
|
||||
this.showDatePicker = event.checked;
|
||||
if (event.checked) {
|
||||
this.form.get('scheduleDate')?.setValidators(Validators.required);
|
||||
this.form.get('scheduleTime')?.setValidators(Validators.required);
|
||||
} else {
|
||||
this.form.get('scheduleDate')?.clearValidators();
|
||||
this.form.get('scheduleTime')?.clearValidators();
|
||||
}
|
||||
this.form.get('scheduleDate')?.updateValueAndValidity();
|
||||
this.form.get('scheduleTime')?.updateValueAndValidity();
|
||||
}
|
||||
|
||||
edit(): void {
|
||||
|
@ -29,12 +75,14 @@ export class CommandDetailComponent {
|
|||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
if (result) {
|
||||
console.log('Comando editado:', result);
|
||||
this.data = result;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
cancel(): void {
|
||||
console.log('Comando recibido:', this.data); // Muestra el comando en la consola
|
||||
this.dialogRef.close(); // Cierra el modal sin hacer nada
|
||||
console.log('Comando cancelado');
|
||||
this.dialogRef.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,10 +32,14 @@ export class CommandsComponent implements OnInit {
|
|||
}
|
||||
|
||||
openCommandDetailModal(command: any): void {
|
||||
this.dialog.open(CommandDetailComponent, {
|
||||
const dialogRef = this.dialog.open(CommandDetailComponent, {
|
||||
width: '800px',
|
||||
data: command
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
this.loadCommands();
|
||||
});
|
||||
}
|
||||
|
||||
openCreateCommandModal(): void {
|
||||
|
@ -44,22 +48,9 @@ export class CommandsComponent implements OnInit {
|
|||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
if (result) {
|
||||
this.loadCommands();
|
||||
}
|
||||
this.loadCommands();
|
||||
});
|
||||
}
|
||||
|
||||
openEditCommandModal(command: any): void {
|
||||
const dialogRef = this.dialog.open(CreateCommandComponent, {
|
||||
width: '600px',
|
||||
data: { command } // Pasar el comando para editar
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
if (result) {
|
||||
this.loadCommands();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,62 +1,43 @@
|
|||
/* Estilo general para el modal */
|
||||
.mat-dialog-container {
|
||||
padding: 24px;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* Título del modal */
|
||||
.mat-dialog-title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
/* Contenedor del formulario */
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* Espaciado entre campos */
|
||||
mat-form-field {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
/* Estilos para los botones */
|
||||
button {
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
/* Botón de añadir (primario) */
|
||||
button[mat-flat-button] {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Botón de cancelar (secundario) */
|
||||
button[mat-button] {
|
||||
color: #666;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
background: #f5f5f5;
|
||||
padding: 8px 16px;
|
||||
}
|
||||
|
||||
/* Botón de añadir (primario) */
|
||||
button[mat-flat-button][color="primary"] {
|
||||
background-color: #3f51b5;
|
||||
color: #fff;
|
||||
border-radius: 4px;
|
||||
padding: 8px 16px;
|
||||
}
|
||||
|
||||
mat-checkbox {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.dialog-title {
|
||||
font-size: 1.5em;
|
||||
color: #343a40;
|
||||
margin: 0;
|
||||
border-bottom: 2px solid #007bff;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.command-form {
|
||||
padding: 20px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.form-field {
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.checkbox-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.cancel-button {
|
||||
margin-right: 10px;
|
||||
color: #dc3545;
|
||||
}
|
||||
|
||||
.submit-button {
|
||||
background-color: #007bff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.submit-button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
|
|
@ -1,26 +1,28 @@
|
|||
<h2 mat-dialog-title>{{ isEditMode ? 'Editar Comando' : 'Añadir Comando' }}</h2>
|
||||
<h2 mat-dialog-title class="dialog-title">{{ isEditMode ? 'Editar Comando' : 'Añadir Comando' }}</h2>
|
||||
|
||||
<form [formGroup]="createCommandForm" (ngSubmit)="onSubmit()">
|
||||
<mat-form-field appearance="fill">
|
||||
<form [formGroup]="createCommandForm" (ngSubmit)="onSubmit()" class="command-form">
|
||||
<mat-form-field appearance="fill" class="form-field">
|
||||
<mat-label>Nombre</mat-label>
|
||||
<input matInput formControlName="name" placeholder="Nombre del comando" required>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-form-field appearance="fill" class="form-field">
|
||||
<mat-label>Script</mat-label>
|
||||
<textarea matInput formControlName="script" placeholder="Script del comando" required></textarea>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-checkbox formControlName="readOnly">Solo lectura</mat-checkbox>
|
||||
<mat-checkbox formControlName="enabled">Habilitado</mat-checkbox>
|
||||
<div class="checkbox-group">
|
||||
<mat-checkbox formControlName="readOnly">Solo lectura</mat-checkbox>
|
||||
<mat-checkbox formControlName="enabled">Habilitado</mat-checkbox>
|
||||
</div>
|
||||
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-form-field appearance="fill" class="form-field">
|
||||
<mat-label>Comentarios</mat-label>
|
||||
<textarea matInput formControlName="comments" placeholder="Comentarios"></textarea>
|
||||
</mat-form-field>
|
||||
|
||||
<div mat-dialog-actions>
|
||||
<button mat-button (click)="onCancel()">Cancelar</button>
|
||||
<button mat-flat-button color="primary" type="submit">{{ isEditMode ? 'Guardar' : 'Añadir' }}</button>
|
||||
<div mat-dialog-actions class="action-buttons">
|
||||
<button mat-button (click)="onCancel()" class="cancel-button">Cancelar</button>
|
||||
<button mat-flat-button color="primary" type="submit" class="submit-button">{{ isEditMode ? 'Guardar' : 'Añadir' }}</button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -42,7 +42,7 @@ export class CreateCommandComponent {
|
|||
if (this.isEditMode) {
|
||||
this.http.patch(`${this.apiUrl}/${this.data.command.uuid}`, commandData).subscribe(
|
||||
response => {
|
||||
this.dialogRef.close(true);
|
||||
this.dialogRef.close(commandData);
|
||||
},
|
||||
error => {
|
||||
console.error('Error editing command', error);
|
||||
|
|
Loading…
Reference in New Issue