-
+
Selecciona una opción @@ -41,9 +46,9 @@
- - - + + + @@ -55,12 +60,12 @@
-
+
- + - + {{ result.name }} @@ -102,7 +107,7 @@
-
+
diff --git a/ogWebconsole/src/app/components/groups/components/advanced-search/advanced-search.component.ts b/ogWebconsole/src/app/components/groups/components/advanced-search/advanced-search.component.ts index a0e7bf9..695e0e4 100644 --- a/ogWebconsole/src/app/components/groups/components/advanced-search/advanced-search.component.ts +++ b/ogWebconsole/src/app/components/groups/components/advanced-search/advanced-search.component.ts @@ -23,6 +23,7 @@ import { Router } from '@angular/router'; import { CreatePxeBootFileComponent } from "../../../ogboot/pxe-boot-files/create-pxeBootFile/create-pxe-boot-file/create-pxe-boot-file.component"; +import { JoyrideService } from 'ngx-joyride'; @Component({ @@ -69,7 +70,8 @@ export class AdvancedSearchComponent { private toastService: ToastrService, private _bottomSheet: MatBottomSheet, private http: HttpClient, - private router: Router + private router: Router, + private joyrideService: JoyrideService ) {} ngOnInit(): void { @@ -472,4 +474,23 @@ export class AdvancedSearchComponent { } } + iniciarTour(): void { + this.joyrideService.startTour({ + steps: [ + 'title2Step', + 'filterSelectionStep', + 'viewModeStep', + 'filtersStep', + 'selectAllStep', + 'saveFiltersStep', + 'sendActionStep', + 'addPxeStep', + 'resultsStep', + 'paginationStep' + ], + showPrevButton: true, + themeColor: '#3f51b5' + }); + } + } diff --git a/ogWebconsole/src/app/components/groups/components/client-tab-view/client-tab-view.component.html b/ogWebconsole/src/app/components/groups/components/client-tab-view/client-tab-view.component.html index 52375fd..5b80b00 100644 --- a/ogWebconsole/src/app/components/groups/components/client-tab-view/client-tab-view.component.html +++ b/ogWebconsole/src/app/components/groups/components/client-tab-view/client-tab-view.component.html @@ -1,49 +1,57 @@ -
-

Administrar clientes

-
- - -
-
- -
- - Buscar nombre de cliente - - search - Pulsar 'enter' para buscar - - - Buscar IP - - search - Pulsar 'enter' para buscar - - - Buscar MAC - - search - Pulsar 'enter' para buscar - - - U. Organizativa - - - {{ unit.name }} - - - +
+ +

Administrar clientes

+
+ +
+
-
- -
+ -
- +
+ + Buscar nombre de cliente + + search + Pulsar 'enter' para buscar + + + + Buscar IP + + search + Pulsar 'enter' para buscar + + + + Buscar MAC + + search + Pulsar 'enter' para buscar + + + + U. Organizativa + + + {{ unit.name }} + + + +
+ +
+ +
+ +
+
- - -
{{ column.header }} +
{{ client.name }}
@@ -51,7 +59,6 @@
{{ client.mac }}
- {{ column.cell(client) }}
Acciones + - + @@ -88,7 +93,8 @@
-
+ +
-

Administrar unidades organizativas

+ +

Administrar unidades organizativas

- - + +
+ -
+ +
Buscar nombre de OU search Pulsar 'enter' para buscar + Tipo - + Todos Centro Grupos de aulas @@ -24,28 +30,29 @@
- + +
- -
{{ column.header }} + {{ column.cell(ou) }} - + event_available - event_busy + event_busy - - {{ ou.type }} + + {{ ou.type }} Acciones + - +
-
+ +
-
-

Administrar grupos

-
- - - +
+ +

Administrar grupos

+
+ + + + +
+
- + Centros + [ngClass]="{'selected-item': unidad === selectedUnidad, 'clickable-item': true}" + (click)="onSelectUnidad(unidad)">
apartment {{ unidad.name }} @@ -23,48 +41,37 @@ more_vert + + + + @@ -74,7 +81,11 @@ - + +
@@ -93,7 +104,9 @@ info No hay elementos internos
- +
apartment @@ -108,24 +121,44 @@ more_vert + + + + + +
@@ -136,12 +169,15 @@
+ + + diff --git a/ogWebconsole/src/app/components/groups/groups.component.ts b/ogWebconsole/src/app/components/groups/groups.component.ts index 27648bd..42baf1b 100644 --- a/ogWebconsole/src/app/components/groups/groups.component.ts +++ b/ogWebconsole/src/app/components/groups/groups.component.ts @@ -25,6 +25,9 @@ import {ClientTabViewComponent} from "./components/client-tab-view/client-tab-vi import { OrganizationalUnitTabViewComponent } from "./components/organizational-unit-tab-view/organizational-unit-tab-view.component"; +import { ExecuteCommandComponent } from '../commands/main-commands/execute-command/execute-command.component'; +import { ExecuteCommandOuComponent } from './shared/execute-command-ou/execute-command-ou.component'; +import { JoyrideService } from 'ngx-joyride'; @Component({ selector: 'app-groups', @@ -67,7 +70,8 @@ export class GroupsComponent implements OnInit { public dialog: MatDialog, private toastService: ToastrService, private _bottomSheet: MatBottomSheet, - private http: HttpClient + private http: HttpClient, + private joyrideService: JoyrideService ) {} ngOnInit(): void { @@ -298,6 +302,21 @@ export class GroupsComponent implements OnInit { } } + onExecuteCommand(event: MouseEvent, child: any, name: string, type:string): void { + console.log('Executing command on:', child); + + this.dialog.open(ExecuteCommandOuComponent, { + width: '50%', + data: { childUnitUuid: child } + }).afterClosed().subscribe((result) => { + if (result) { + console.log('Comando ejecutado con éxito'); + } else { + console.log('Ejecución de comando cancelada'); + } + }); + } + openSnackBar(isError: boolean, message: string) { if (isError) { this.toastService.error(' Error al eliminar la entidad: ' + message, 'Error'); @@ -432,4 +451,11 @@ export class GroupsComponent implements OnInit { const dialogRef = this.dialog.open(AcctionsModalComponent, { data: { selectedElements: this.selectedElements }, width: '700px'}); } + iniciarTour(): void { + this.joyrideService.startTour({ + steps: ['titleStep', 'addStep', 'keyStep', 'unitStep', 'elementsStep', 'tabsStep'], + showPrevButton: true, + themeColor: '#3f51b5' + }); + } } diff --git a/ogWebconsole/src/app/components/groups/shared/execute-command-ou/execute-command-ou.component.css b/ogWebconsole/src/app/components/groups/shared/execute-command-ou/execute-command-ou.component.css new file mode 100644 index 0000000..b908066 --- /dev/null +++ b/ogWebconsole/src/app/components/groups/shared/execute-command-ou/execute-command-ou.component.css @@ -0,0 +1,57 @@ +.form-container { + display: flex; + flex-direction: column; + gap: 16px; + padding: 16px; + } + + .command-form { + width: 100%; + } + + .full-width { + width: 100%; + } + + .checkbox-group { + display: flex; + flex-direction: column; + gap: 8px; + padding-top: 8px; + } + + .checkbox-group label { + font-weight: bold; + margin-bottom: 8px; + } + + .mat-checkbox { + margin-left: 8px; + } + + .mat-dialog-title { + font-size: 20px; + font-weight: 600; + margin-bottom: 12px; + } + + .mat-dialog-content { + max-height: 60vh; + overflow-y: auto; + } + + .mat-dialog-actions { + display: flex; + justify-content: flex-end; + gap: 8px; + padding: 16px; + } + + button[mat-button] { + font-weight: 500; + } + + button[mat-button]:disabled { + color: rgba(0, 0, 0, 0.38); + } + \ No newline at end of file diff --git a/ogWebconsole/src/app/components/groups/shared/execute-command-ou/execute-command-ou.component.html b/ogWebconsole/src/app/components/groups/shared/execute-command-ou/execute-command-ou.component.html new file mode 100644 index 0000000..81c14d4 --- /dev/null +++ b/ogWebconsole/src/app/components/groups/shared/execute-command-ou/execute-command-ou.component.html @@ -0,0 +1,45 @@ +

Ejecutar Comando o Grupo de Comandos

+ + + + + + Seleccione Comando + + {{ command.name }} + + + + + Seleccione Grupo de Comandos + + {{ group.name }} + + + +
+ +
+ + {{ client.name }} + +
+
+

No hay clientes disponibles

+
+
+ + +
+ + + + + diff --git a/ogWebconsole/src/app/components/groups/shared/execute-command-ou/execute-command-ou.component.ts b/ogWebconsole/src/app/components/groups/shared/execute-command-ou/execute-command-ou.component.ts new file mode 100644 index 0000000..7831cab --- /dev/null +++ b/ogWebconsole/src/app/components/groups/shared/execute-command-ou/execute-command-ou.component.ts @@ -0,0 +1,120 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { HttpClient } from '@angular/common/http'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { ToastrService } from 'ngx-toastr'; + +@Component({ + selector: 'app-execute-command-ou', + templateUrl: './execute-command-ou.component.html', + styleUrls: ['./execute-command-ou.component.css'] +}) +export class ExecuteCommandOuComponent implements OnInit { + form: FormGroup; + clients: any[] = []; + commands: any[] = []; + commandGroups: any[] = []; + baseUrl: string = import.meta.env.NG_APP_BASE_API_URL; + + constructor( + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any, + private http: HttpClient, + private fb: FormBuilder, + private toastService: ToastrService, + ) { + this.form = this.fb.group({ + selectedCommand: [null], + selectedCommandGroup: [null], + clientSelection: [[]] + }); + } + + ngOnInit(): void { + this.loadClients(); + this.loadCommands(); + this.loadCommandGroups(); + } + + loadClients(): void { + this.http.get(`${this.baseUrl}/organizational-units/${this.data.childUnitUuid}`).subscribe( + response => { + this.clients = this.getAllClients(response); + const clientIds = this.clients.map(client => client.uuid); + this.form.get('clientSelection')?.setValue(clientIds); + }, + error => console.error('Error al cargar los clientes:', error) + ); + } + + getAllClients(unit: any): any[] { + let allClients = unit.clients || []; + if (unit.children && unit.children.length > 0) { + unit.children.forEach((child: any) => { + allClients = allClients.concat(this.getAllClients(child)); + }); + } + return allClients; + } + + loadCommands(): void { + this.http.get(`${this.baseUrl}/commands?page=1&itemsPerPage=30`).subscribe( + response => { + this.commands = response['hydra:member'] || []; + }, + error => this.toastService.error('Error al cargar comandos:', error) + ); + } + + loadCommandGroups(): void { + this.http.get(`${this.baseUrl}/command-groups?page=1&itemsPerPage=30`).subscribe( + response => { + this.commandGroups = response['hydra:member'] || []; + }, + error => this.toastService.error('Error al cargar grupos de comandos:', error) + ); + } + + 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]); + } + } + + executeCommand(): void { + const selectedCommandUuid = this.form.get('selectedCommand')?.value || this.form.get('selectedCommandGroup')?.value; + const isCommandGroup = !!this.form.get('selectedCommandGroup')?.value; + + if (!selectedCommandUuid) { + console.warn('No se ha seleccionado ningún comando o grupo de comandos'); + return; + } + + const payload = { + clients: (this.form.get('clientSelection')?.value || []).map((clientId: string) => `/clients/${clientId}`) + }; + + const url = isCommandGroup + ? `${this.baseUrl}/command-groups/${selectedCommandUuid}/execute` + : `${this.baseUrl}/commands/${selectedCommandUuid}/execute`; + + this.http.post(url, payload) + .subscribe({ + next: () => { + this.toastService.success('Comando ejecutado con éxito'); + this.dialogRef.close(true); + }, + error: (error) => { + this.toastService.error('Error al ejecutar el comando:', error); + this.dialogRef.close(false); + } + }); + } + + closeModal(): void { + this.dialogRef.close(false); + } +} diff --git a/ogWebconsole/src/app/components/images/images.component.html b/ogWebconsole/src/app/components/images/images.component.html index fa31c21..1e19332 100644 --- a/ogWebconsole/src/app/components/images/images.component.html +++ b/ogWebconsole/src/app/components/images/images.component.html @@ -1,78 +1,64 @@ -
-

Administrar imágenes

-
- -
+
+ +

+ Administrar imágenes +

+
+
- +
-
- - Buscar nombre de imagen - - search - Pulsar 'enter' para buscar - -
+ +
+ + Buscar nombre de imagen + + search + Pulsar 'enter' para buscar + +
- - - - - - - - - - - - - -
{{ column.header }} - - - - {{ image[column.columnDef] }} - - + + + + + +>>>>>>> c168c87fc9ebcc4b5cf9a68effa16bdb2a848e00 - - - - {{ image[column.columnDef] ? 'check_circle' : 'cancel' }} - - + + + + + + +
{{ column.header }} + + + {{ image[column.columnDef] ? 'check_circle' : 'cancel' }} + + + + {{ column.cell(image) }} + + Acciones + + +
- - - {{ column.cell(image) }} - -
Acciones - - - - - - - - -
- -
- - -
+
+ + +
diff --git a/ogWebconsole/src/app/components/images/images.component.ts b/ogWebconsole/src/app/components/images/images.component.ts index c9baa32..6c41a62 100644 --- a/ogWebconsole/src/app/components/images/images.component.ts +++ b/ogWebconsole/src/app/components/images/images.component.ts @@ -10,6 +10,7 @@ import {DeleteModalComponent} from "../../shared/delete_modal/delete-modal/delet import {ServerInfoDialogComponent} from "../ogdhcp/og-dhcp-subnets/server-info-dialog/server-info-dialog.component"; import {Observable} from "rxjs"; import {InfoImageComponent} from "../ogboot/pxe-images/info-image/info-image/info-image.component"; +import { JoyrideService } from 'ngx-joyride'; @Component({ selector: 'app-images', @@ -70,7 +71,8 @@ export class ImagesComponent implements OnInit { constructor( public dialog: MatDialog, private http: HttpClient, - private toastService: ToastrService + private toastService: ToastrService, + private joyrideService: JoyrideService ) {} ngOnInit(): void { @@ -178,4 +180,20 @@ export class ImagesComponent implements OnInit { break; } } + iniciarTour(): void { + this.joyrideService.startTour({ + steps: [ + 'imagesTitleStep', + 'addImageButton', + 'searchImageField', + 'imagesTable', + 'actionsHeader', + 'editImageButton', + 'deleteImageButton', + 'imagesPagination' + ], + showPrevButton: true, + themeColor: '#3f51b5' + }); + } } diff --git a/ogWebconsole/src/app/components/ogboot/ogboot-status/ogboot-status.component.css b/ogWebconsole/src/app/components/ogboot/ogboot-status/ogboot-status.component.css index 29859f4..a4c857a 100644 --- a/ogWebconsole/src/app/components/ogboot/ogboot-status/ogboot-status.component.css +++ b/ogWebconsole/src/app/components/ogboot/ogboot-status/ogboot-status.component.css @@ -1,4 +1,11 @@ - +.header-container { + display: flex; + justify-content: space-between; + align-items: center; + height: 100px; + padding: 10px; +} + .disk-usage-info{ display: flex; justify-content: start; diff --git a/ogWebconsole/src/app/components/ogboot/ogboot-status/ogboot-status.component.html b/ogWebconsole/src/app/components/ogboot/ogboot-status/ogboot-status.component.html index a4b385a..a9ac124 100644 --- a/ogWebconsole/src/app/components/ogboot/ogboot-status/ogboot-status.component.html +++ b/ogWebconsole/src/app/components/ogboot/ogboot-status/ogboot-status.component.html @@ -1,59 +1,64 @@
-

OgBoot server Status

- -
-
-

Uso de disco

- - -
-

Total: {{ diskUsage.total }}

-

Ocupado: {{ diskUsage.used }}

-

Disponible: {{ diskUsage.available }}

-

Libre: {{ diskUsage.percentage }}

-
-
- -
-

Servicios

-
    -
  • - - {{ service.name }}: {{ service.status }} -
  • -
+
+

OgBoot server Status

+ +
+ +
+
+

Uso de disco

+ + +
+

Total: {{ formatBytes(diskUsage.total) }}

+

Ocupado: {{ formatBytes(diskUsage.used) }}

+

Disponible: {{ formatBytes(diskUsage.available) }}

+

Libre: {{ diskUsage.percentage }}%

-
-

OGLives instalados

- - - - - - - - - - - - - - - - - -
IDKernelArchitectureRevision
{{ oglive.id }}{{ oglive.kernel }}{{ oglive.architecture }}{{ oglive.revision }}
+
+

Servicios

+
    +
  • + + {{ service.name }}: {{ service.status }} +
  • +
+ +
+

OGLives instalados

+ + + + + + + + + + + + + + + + + +
IDKernelArchitectureRevision
{{ oglive.id }}{{ oglive.kernel }}{{ oglive.architecture }}{{ oglive.revision }}
+
+
diff --git a/ogWebconsole/src/app/components/ogboot/ogboot-status/ogboot-status.component.ts b/ogWebconsole/src/app/components/ogboot/ogboot-status/ogboot-status.component.ts index f15154f..481a2eb 100644 --- a/ogWebconsole/src/app/components/ogboot/ogboot-status/ogboot-status.component.ts +++ b/ogWebconsole/src/app/components/ogboot/ogboot-status/ogboot-status.component.ts @@ -1,5 +1,6 @@ import { Component, OnInit } from '@angular/core'; import { HttpClient } from '@angular/common/http'; +import { JoyrideService } from 'ngx-joyride'; @Component({ selector: 'app-ogboot-status', @@ -23,7 +24,7 @@ export class OgbootStatusComponent implements OnInit { domain: ['#FF6384', '#3f51b5'] }; - constructor(private http: HttpClient) {} + constructor(private http: HttpClient, private joyrideService: JoyrideService) {} ngOnInit(): void { this.loadStatus(); @@ -56,4 +57,30 @@ export class OgbootStatusComponent implements OnInit { status: this.servicesStatus[key] })); } + + formatBytes(bytes: number): string { + if (bytes >= 1e9) { + return (bytes / 1e9).toFixed(2) + ' GB'; + } else if (bytes >= 1e6) { + return (bytes / 1e6).toFixed(2) + ' MB'; + } else if (bytes >= 1e3) { + return (bytes / 1e3).toFixed(2) + ' KB'; + } else { + return bytes + ' B'; + } + } + + iniciarTour(): void { + this.joyrideService.startTour({ + steps: [ + 'titleStep', + 'diskUsageStep', + 'servicesStatusStep', + 'oglivesStep' + ], + showPrevButton: true, + themeColor: '#3f51b5' + }); + } + } diff --git a/ogWebconsole/src/app/components/ogboot/pxe-boot-files/pxe-boot-files.component.html b/ogWebconsole/src/app/components/ogboot/pxe-boot-files/pxe-boot-files.component.html index 0b161ad..6f12dcd 100644 --- a/ogWebconsole/src/app/components/ogboot/pxe-boot-files/pxe-boot-files.component.html +++ b/ogWebconsole/src/app/components/ogboot/pxe-boot-files/pxe-boot-files.component.html @@ -1,10 +1,12 @@ -
-

Netboot avanzado

+

Netboot avanzado

+
- + Selecciona Unidad Organizacional Cargando unidades... @@ -15,7 +17,7 @@ Este campo es obligatorio - + Selecciona aula No hay aulas disponibles @@ -29,17 +31,17 @@
- + Seleccione plantilla para aplicar a todos los clientes - + {{ option.name }} - +
- + Id {{element.id}} @@ -53,7 +55,7 @@ Plantilla - + Seleccione una plantilla Ninguna @@ -65,7 +67,6 @@ - diff --git a/ogWebconsole/src/app/components/ogboot/pxe-boot-files/pxe-boot-files.component.ts b/ogWebconsole/src/app/components/ogboot/pxe-boot-files/pxe-boot-files.component.ts index e88153e..1583aca 100644 --- a/ogWebconsole/src/app/components/ogboot/pxe-boot-files/pxe-boot-files.component.ts +++ b/ogWebconsole/src/app/components/ogboot/pxe-boot-files/pxe-boot-files.component.ts @@ -5,6 +5,7 @@ import { ToastrService } from 'ngx-toastr'; import { PageEvent } from '@angular/material/paginator'; import {Observable} from "rxjs"; import {ServerInfoDialogComponent} from "../../ogdhcp/og-dhcp-subnets/server-info-dialog/server-info-dialog.component"; +import { JoyrideService } from 'ngx-joyride'; @Component({ selector: 'app-pxe-boot-files', @@ -32,7 +33,8 @@ export class PxeBootFilesComponent implements OnInit { constructor( private fb: FormBuilder, private http: HttpClient, - private toastService: ToastrService + private toastService: ToastrService, + private joyrideService: JoyrideService ) { this.taskForm = this.fb.group({ organizationalUnit: ['', Validators.required], @@ -155,4 +157,21 @@ export class PxeBootFilesComponent implements OnInit { this.itemsPerPage = event.pageSize; this.fetchPxeTemplates(); } + + iniciarTour(): void { + this.joyrideService.startTour({ + steps: [ + 'titleStep', + 'selectUnitStep', + 'selectClassStep', + 'applyToAllStep', + 'saveButtonStep', + 'tableStep', + 'selectTemplateStep' + ], + showPrevButton: true, + themeColor: '#3f51b5' + }); + } + } diff --git a/ogWebconsole/src/app/components/ogboot/pxe-images/pxe-images.component.html b/ogWebconsole/src/app/components/ogboot/pxe-images/pxe-images.component.html index 96e0993..6fd64f3 100644 --- a/ogWebconsole/src/app/components/ogboot/pxe-images/pxe-images.component.html +++ b/ogWebconsole/src/app/components/ogboot/pxe-images/pxe-images.component.html @@ -1,41 +1,47 @@ - + Información en servidor ogBoot -
- +
- +
-

Administrar imágenes

+ +

Administrar imágenes

- +
+ +
- + Buscar nombre de imagen search Pulsar 'enter' para buscar - + + Imagen por defecto - + Todos No - + + Instalado servidor ogBoot Todos @@ -44,11 +50,11 @@
- + +
- -
{{ column.header }} - + {{ image[column.columnDef] ? 'check_circle' : 'cancel' }} @@ -76,15 +82,14 @@ {{ column.cell(image) }} - Acciones + - +
-
+ +
{{ isEditMode ? 'Editar' : 'Añadir' }} plantilla +

{{ isEditMode ? 'Editar' : 'Añadir' }} plantilla

- Nombre de la Plantilla @@ -23,9 +22,19 @@
- - - + +
+ + + + + + +
+ + +
+
diff --git a/ogWebconsole/src/app/components/ogboot/pxe/create-pxeTemplate/create-pxe-template.component.ts b/ogWebconsole/src/app/components/ogboot/pxe/create-pxeTemplate/create-pxe-template.component.ts index b16bc94..14d208a 100644 --- a/ogWebconsole/src/app/components/ogboot/pxe/create-pxeTemplate/create-pxe-template.component.ts +++ b/ogWebconsole/src/app/components/ogboot/pxe/create-pxeTemplate/create-pxe-template.component.ts @@ -1,9 +1,9 @@ import { HttpClient } from '@angular/common/http'; import { Component, Inject, OnInit } from '@angular/core'; import { FormGroup, FormBuilder, Validators } from '@angular/forms'; -import {MatDialogRef, MAT_DIALOG_DATA, MatDialog} from '@angular/material/dialog'; +import { MatDialogRef, MAT_DIALOG_DATA, MatDialog } from '@angular/material/dialog'; import { ToastrService } from 'ngx-toastr'; -import {DeleteModalComponent} from "../../../../shared/delete_modal/delete-modal/delete-modal.component"; +import { DeleteModalComponent } from "../../../../shared/delete_modal/delete-modal/delete-modal.component"; @Component({ selector: 'app-create-pxe-template', @@ -17,6 +17,39 @@ export class CreatePxeTemplateComponent implements OnInit { isEditMode: boolean = false; clients: any[] = []; + templateModels = { + ogLive: `#!ipxe +set timeout 0 +set timeout-style hidden +set ISODIR __OGLIVE__ +set default 0 +set kernelargs __INFOHOST__ +:try_iso +kernel http://__SERVERIP__/tftpboot/\${ISODIR}/ogvmlinuz \${kernelargs} || goto fallback +initrd http://__SERVERIP__/tftpboot/\${ISODIR}/oginitrd.img +boot + +:fallback +set ISODIR ogLive +kernel http://__SERVERIP__/tftpboot/\${ISODIR}/ogvmlinuz \${kernelargs} +initrd http://__SERVERIP__/tftpboot/\${ISODIR}/oginitrd.img +boot`, + + disco: `#!ipxe + +iseq \${platform} efi && goto uefi_boot || goto bios_boot + +:bios_boot +echo "Running in BIOS mode - Booting first disk" +chain http://__SERVERIP__/tftpboot/grub.exe --config-file="title FirstHardDisk;chainloader (hd0)+1;rootnoverify (hd0);boot" || echo "Failed to boot in BIOS mode" +exit + +:uefi_boot +echo "Running in UEFI mode - Booting first disk" +sanboot --no-describe --drive 0 --filename \\EFI\\grub\\Boot\\grubx64.efi || echo "Failed to boot in UEFI mode" +exit` + }; + constructor( public dialogRef: MatDialogRef, public dialog: MatDialog, @@ -29,8 +62,8 @@ export class CreatePxeTemplateComponent implements OnInit { ngOnInit() { this.isEditMode = !!this.data; - if (this.isEditMode){ - this.getPxeClients() + if (this.isEditMode) { + this.getPxeClients(); } this.templateForm = this.fb.group({ @@ -50,7 +83,7 @@ export class CreatePxeTemplateComponent implements OnInit { getPxeClients(): void { this.http.get(`${this.baseUrl}/clients?template.id=${this.data.id}`).subscribe({ next: data => { - this.clients = data['hydra:member'] + this.clients = data['hydra:member']; }, error: error => { console.error('Error al obtener los clientes PXE:', error); @@ -67,12 +100,10 @@ export class CreatePxeTemplateComponent implements OnInit { this.http.post(`${this.baseUrl}/pxe-templates`, payload).subscribe({ next: data => { - console.log('Plantilla PXE creada:', data); this.toastService.success('Plantilla PXE creada exitosamente'); this.dialogRef.close(true); }, error: error => { - console.error('Error al crear la plantilla PXE:', error); this.toastService.error('Error al crear la plantilla PXE'); this.dialogRef.close(false); } @@ -98,13 +129,19 @@ export class CreatePxeTemplateComponent implements OnInit { }); } + loadTemplateModel(type: 'ogLive' | 'disco'): void { + const selectedContent = this.templateModels[type]; + this.templateForm.get('templateContent')?.setValue(selectedContent); + this.toastService.info(`Plantilla ${type} cargada.`); + } + addClientToTemplate(client: any): void { const postData = { client: client['@id'] }; this.http.post(`${this.baseUrl}/pxe-templates/${this.data.uuid}/sync-client`, postData).subscribe( - response => { + () => { this.toastService.success('Clientes asignados correctamente'); }, error => { @@ -126,11 +163,12 @@ export class CreatePxeTemplateComponent implements OnInit { this.toastService.success('Cliente eliminado exitosamente'); this.dialogRef.close(); }, - error: (error) => { + error: error => { this.toastService.error(error.error['hydra:description']); } }); - }}) + } + }); } onCancel(): void { diff --git a/ogWebconsole/src/app/components/ogboot/pxe/pxe.component.html b/ogWebconsole/src/app/components/ogboot/pxe/pxe.component.html index 4612525..8f10354 100644 --- a/ogWebconsole/src/app/components/ogboot/pxe/pxe.component.html +++ b/ogWebconsole/src/app/components/ogboot/pxe/pxe.component.html @@ -1,10 +1,10 @@ - + Información en servidor ogBoot
- +
@@ -12,34 +12,39 @@ -
-

Administrar plantillas PXE

+ +

Administrar plantillas PXE

- +
+ +
- + Buscar nombre de plantilla search Pulsar 'enter' para buscar - + Creada en ogBoot - + Todos No
- + +
- - + -
{{ column.header }} + {{ image[column.columnDef] ? 'check_circle' : 'cancel' }} @@ -52,19 +57,19 @@ Acciones + - - + + - + @@ -74,7 +79,8 @@
-
+ +
Añade clientes a {{data.subnetName}} - - - - - {{ client.name }} - - + + Unidad Organizativa + + {{ unit.name }} + -
-

Clientes seleccionados:

-
    -
  • + + Subunidad Organizativa + + {{ child.name }} + + + +
    + +
    + {{ client.name }} - -
  • -
+ +
+
+

No hay clientes disponibles

+
diff --git a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/add-clients-to-subnet/add-clients-to-subnet.component.ts b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/add-clients-to-subnet/add-clients-to-subnet.component.ts index 8efab27..33dbecd 100644 --- a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/add-clients-to-subnet/add-clients-to-subnet.component.ts +++ b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/add-clients-to-subnet/add-clients-to-subnet.component.ts @@ -1,10 +1,8 @@ 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"; +import { FormControl } from '@angular/forms'; +import { ToastrService } from 'ngx-toastr'; @Component({ selector: 'app-add-clients-to-subnet', @@ -13,59 +11,93 @@ import {ToastrService} from "ngx-toastr"; }) export class AddClientsToSubnetComponent implements OnInit { baseUrl: string = import.meta.env.NG_APP_BASE_API_URL; + units: any[] = []; + childUnits: any[] = []; clients: any[] = []; - selectedClients: any[] = []; + selectedClients: string[] = []; loading: boolean = true; - filters: { [key: string]: string } = {}; - filteredClients!: Observable; - clientControl = new FormControl(); + unitControl = new FormControl(); + childUnitControl = new FormControl(); constructor( private http: HttpClient, public dialogRef: MatDialogRef, 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.loadUnits(); + } - 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())) + loadUnits() { + this.http.get(`${this.baseUrl}/organizational-units?page=1&itemsPerPage=50`).subscribe( + response => { + this.units = response['hydra:member'].filter((unit: { type: string; }) => unit.type === 'organizational-unit'); + this.loading = false; + }, + error => console.error('Error fetching organizational units:', error) ); } - loadClients() { - this.http.get( `${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 parent units:', error); - this.loading = false; + onUnitChange(unitId: string): void { + const unit = this.units.find(unit => unit.uuid === unitId); + this.childUnits = unit ? this.getAllChildren(unit) : []; + this.clients = []; + this.childUnitControl.setValue(null); + this.selectedClients = []; + } + + 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.selectedClients = []; + } + + toggleClientSelection(clientId: string): void { + const index = this.selectedClients.indexOf(clientId); + if (index >= 0) { + this.selectedClients.splice(index, 1); + } else { + this.selectedClients.push(clientId); + } + } + + toggleSelectAll(): void { + if (this.areAllClientsSelected()) { + this.selectedClients = []; + } else { + this.selectedClients = this.clients.map(client => client.uuid); + } + } + + areAllClientsSelected(): boolean { + return this.selectedClients.length === this.clients.length; } save() { - this.selectedClients.forEach(client => { - const postData = { - client: client['@id'] - }; + this.selectedClients.forEach(clientId => { + const postData = { client: `/clients/${clientId}` }; this.http.post(`${this.baseUrl}/og-dhcp/server/${this.data.subnetUuid}/post-host`, postData).subscribe( response => { - this.toastService.success(`Cliente ${client.name} asignado correctamente`); + this.toastService.success(`Cliente 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']}`); + console.error(`Error al asignar el cliente:`, error); + this.toastService.error(`Error al asignar el cliente: ${error.error['hydra:description']}`); } ); }); @@ -76,27 +108,4 @@ export class AddClientsToSubnetComponent implements OnInit { 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(''); - } } diff --git a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/create-subnet/create-subnet.component.css b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/create-subnet/create-subnet.component.css index 6f0fb98..36b762b 100644 --- a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/create-subnet/create-subnet.component.css +++ b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/create-subnet/create-subnet.component.css @@ -13,9 +13,9 @@ form{ .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 */ + align-items: flex-start; + justify-content: space-between; + width: 100%; } .text-content { @@ -33,4 +33,3 @@ form{ margin-left: 8px; cursor: pointer; } - diff --git a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/create-subnet/create-subnet.component.html b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/create-subnet/create-subnet.component.html index f7b64f5..6892323 100644 --- a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/create-subnet/create-subnet.component.html +++ b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/create-subnet/create-subnet.component.html @@ -16,21 +16,29 @@ Dirección IP - - Next Server - - - - Boot File Name - - + + + + + Parámetros avanzados + + + + Next Server + + + + Boot File Name + + +
- +
computer
diff --git a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/create-subnet/create-subnet.component.ts b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/create-subnet/create-subnet.component.ts index 7cb8a79..a0d5ef4 100644 --- a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/create-subnet/create-subnet.component.ts +++ b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/create-subnet/create-subnet.component.ts @@ -58,8 +58,8 @@ export class CreateSubnetComponent implements OnInit { name: this.name, netmask: this.netmask, ipAddress: this.ipAddress, - nextServer: this.nextServer, - bootFileName: this.bootFileName + nextServer: this.nextServer || null, + bootFileName: this.bootFileName || null }; if (!this.data){ diff --git a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.html b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.html index e4d2e54..3641600 100644 --- a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.html +++ b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.html @@ -1,57 +1,62 @@ - + Información en servidor ogDHCP
- +
- +
-

Administrar Subredes

+ +

Administrar Subredes

- +
+
- + Buscar nombre de la subred - + search Pulsar 'enter' para buscar - + Buscar netmask - + search Pulsar 'enter' para buscar - + Buscar IP - + search Pulsar 'enter' para buscar - + Buscar Boot file name - + search Pulsar 'enter' para buscar
+ - + +
-
{{ column.header }} - {{ subnet[column.columnDef] ? 'check_circle' : 'cancel' }} @@ -75,9 +80,10 @@ Acciones + + edit +
-
- + +
+
diff --git a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.ts b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.ts index c7fe965..3d49acd 100644 --- a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.ts +++ b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/og-dhcp-subnets.component.ts @@ -7,8 +7,9 @@ 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"; -import {Observable} from "rxjs"; +import { ServerInfoDialogComponent } from "./server-info-dialog/server-info-dialog.component"; +import { Observable } from "rxjs"; +import { JoyrideService } from 'ngx-joyride'; export interface Subnet { '@id': string; @@ -32,7 +33,7 @@ export interface Subnet { templateUrl: './og-dhcp-subnets.component.html', styleUrls: ['./og-dhcp-subnets.component.css'] }) -export class OgDhcpSubnetsComponent { +export class OgDhcpSubnetsComponent { baseUrl: string = import.meta.env.NG_APP_BASE_API_URL; displayedColumns: string[] = ['id', 'name', 'netmask', 'ipAddress', 'nextServer', 'bootFileName', 'synchronized', 'serverId', 'clients', 'actions']; dataSource = new MatTableDataSource([]); @@ -52,14 +53,15 @@ 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: 'synchronized', header: 'Sincronizado', cell: (subnet: Subnet) => `${subnet.synchronized}` }, { columnDef: 'serverId', header: 'Id Servidor DHCP', cell: (subnet: Subnet) => subnet.serverId }, - { columnDef: 'clients', header: 'Lista de clientes', cell: (subnet: Subnet) => `${subnet.clients}`}, + { 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) {} + constructor(public dialog: MatDialog, private http: HttpClient, private toastService: ToastrService, + private joyrideService: JoyrideService) { } ngOnInit() { this.loadSubnets(); @@ -93,7 +95,7 @@ export class OgDhcpSubnetsComponent { }); } - toggleAction(subnet: any, action:string): void { + toggleAction(subnet: any, action: string): void { switch (action) { case 'get': this.http.post(`${this.baseUrl}/og-dhcp/server/${subnet.uuid}/get`, {}).subscribe({ @@ -149,7 +151,8 @@ export class OgDhcpSubnetsComponent { this.toastService.error(error.error['hydra:description']); } }); - }}) + } + }) break; default: console.error('Acción no soportada:', action); @@ -217,4 +220,26 @@ export class OgDhcpSubnetsComponent { this.itemsPerPage = event.pageSize; this.loadSubnets(); } + + iniciarTour(): void { + this.joyrideService.startTour({ + steps: [ + 'serverInfoStep', + 'syncDbStep', + 'viewInfoStep', + 'titleStep', + 'addSubnetStep', + 'searchNameStep', + 'searchNetmaskStep', + 'searchIpStep', + 'searchBootFileStep', + 'tableStep', + 'actionsStep', + 'paginationStep' + ], + showPrevButton: true, + themeColor: '#3f51b5' + }); + } + } diff --git a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/status/status.component.css b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/status/status.component.css index d0cc96f..e0992fd 100644 --- a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/status/status.component.css +++ b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/status/status.component.css @@ -78,11 +78,17 @@ th { .button-container { display: flex; flex-direction: column; - gap: 10px; /* Espacio entre botones */ + gap: 10px; margin-top: 50px; } - +.header-container { + display: flex; + justify-content: space-between; + align-items: center; + height: 100px; + padding: 10px; +} .btn:first-child { margin-left: 0; diff --git a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/status/status.component.html b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/status/status.component.html index 98b1b17..19464a8 100644 --- a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/status/status.component.html +++ b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/status/status.component.html @@ -1,8 +1,13 @@
-

OgDhcp server Status

+
+

OgDhcp server Status

+ +
-
+

Uso de disco

-
+

Servicios

  • - + {{ service.name }}: {{ service.status }}
-
+

Subredes

- - - - - - - + + + + + + + - - - - - - - + + + + + + +
IDBoot file nameNext serverIpOrdenadores
IDBoot file nameNext serverIpOrdenadores
{{ subnet.id }}{{ subnet['boot-file-name'] }}{{ subnet['next-server'] }}{{ subnet.subnet }}{{ subnet.reservations.length }}
{{ subnet.id }}{{ subnet['boot-file-name'] }}{{ subnet['next-server'] }}{{ subnet.subnet }}{{ subnet.reservations.length }}
diff --git a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/status/status.component.ts b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/status/status.component.ts index 44885b3..eb743b4 100644 --- a/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/status/status.component.ts +++ b/ogWebconsole/src/app/components/ogdhcp/og-dhcp-subnets/status/status.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; import {HttpClient} from "@angular/common/http"; +import { JoyrideService } from 'ngx-joyride'; @Component({ selector: 'app-status', @@ -23,7 +24,8 @@ export class StatusComponent { domain: ['#FF6384', '#3f51b5'] }; - constructor(private http: HttpClient) {} + constructor(private http: HttpClient, + private joyrideService: JoyrideService) {} ngOnInit(): void { this.loadStatus(); @@ -55,4 +57,18 @@ export class StatusComponent { status: this.servicesStatus[key] })); } + + iniciarTour(): void { + this.joyrideService.startTour({ + steps: [ + 'titleStep', + 'diskUsageStep', + 'servicesStatusStep', + 'subnetsStep' + ], + showPrevButton: true, + themeColor: '#3f51b5' + }); + } + } diff --git a/ogWebconsole/src/app/components/operative-system/operative-system.component.html b/ogWebconsole/src/app/components/operative-system/operative-system.component.html index 60589b9..0ad1eb3 100644 --- a/ogWebconsole/src/app/components/operative-system/operative-system.component.html +++ b/ogWebconsole/src/app/components/operative-system/operative-system.component.html @@ -1,22 +1,30 @@
-

Administrar sistemas operativos

+ +

+ Administrar sistemas operativos +

- +
+ +
- + Buscar nombre de sistema operativo search Pulsar 'enter' para buscar
- + +
- +
{{ column.header }} + {{ column.cell(image) }} @@ -24,17 +32,22 @@ - AccionesAcciones - - + +
-
+ +
- diff --git a/ogWebconsole/src/app/components/software-profile/create-software-profile/create-software-profile.component.ts b/ogWebconsole/src/app/components/software-profile/create-software-profile/create-software-profile.component.ts index 5398b22..22440a6 100644 --- a/ogWebconsole/src/app/components/software-profile/create-software-profile/create-software-profile.component.ts +++ b/ogWebconsole/src/app/components/software-profile/create-software-profile/create-software-profile.component.ts @@ -1,21 +1,21 @@ -import {Component, Inject} from '@angular/core'; -import {FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms"; -import {HttpClient} from "@angular/common/http"; -import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog"; -import {ToastrService} from "ngx-toastr"; -import {DataService as SoftwareService} from "../../software/data.service"; -import {DataService} from "../data.service"; -import {Observable, startWith} from "rxjs"; +import { Component, Inject, OnInit } from '@angular/core'; +import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; +import { HttpClient } from '@angular/common/http'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { ToastrService } from 'ngx-toastr'; +import { DataService as SoftwareService } from '../../software/data.service'; +import { DataService } from '../data.service'; +import { Observable, startWith } from 'rxjs'; import { debounceTime, switchMap, map } from 'rxjs/operators'; @Component({ selector: 'app-create-software-profile', templateUrl: './create-software-profile.component.html', - styleUrl: './create-software-profile.component.css' + styleUrls: ['./create-software-profile.component.css'] }) -export class CreateSoftwareProfileComponent { +export class CreateSoftwareProfileComponent implements OnInit { baseUrl: string = import.meta.env.NG_APP_BASE_API_URL; - formGroup: FormGroup; + formGroup: FormGroup; private apiUrl = `${this.baseUrl}/software-profiles`; softwareCollection: any[] = []; organizationalUnits: any[] = []; @@ -45,11 +45,13 @@ export class CreateSoftwareProfileComponent { ngOnInit(): void { if (this.data) { - this.load() + this.softwareProfileId = this.data['@id']; + this.patchFormData(); } + this.loadSoftware(); - this.loadOrganizationalUnits() - this.loadOperativeSystems() + this.loadOrganizationalUnits(); + this.loadOperativeSystems(); this.filteredSoftware = this.softwareControl.valueChanges.pipe( startWith(''), @@ -58,42 +60,50 @@ export class CreateSoftwareProfileComponent { ); } + patchFormData(): void { + this.formGroup.patchValue({ + description: this.data.description || '', + comments: this.data.comments || '', + organizationalUnit: this.data.organizationalUnit ? this.data.organizationalUnit['@id'] : null, + operativeSystem: this.data.operativeSystem ? this.data.operativeSystem['@id'] : null, + }); + } + loadSoftware() { - this.http.get( `${this.baseUrl}/software?&page=1&itemsPerPage=10`).subscribe( + this.http.get(`${this.baseUrl}/software?page=1&itemsPerPage=10`).subscribe( response => { this.softwareCollection = response['hydra:member']; }, error => { - console.error('Error fetching parent units:', error); + console.error('Error fetching software:', error); } ); } loadOrganizationalUnits() { - this.http.get( `${this.baseUrl}/organizational-units?&page=1&itemsPerPage=10000`).subscribe( + this.http.get(`${this.baseUrl}/organizational-units?page=1&itemsPerPage=10000`).subscribe( response => { this.organizationalUnits = response['hydra:member']; }, error => { - console.error('Error fetching parent units:', error); + console.error('Error fetching organizational units:', error); } ); } loadOperativeSystems() { - this.http.get( `${this.baseUrl}/operative-systems?&page=1&itemsPerPage=10000`).subscribe( + this.http.get(`${this.baseUrl}/operative-systems?page=1&itemsPerPage=10000`).subscribe( response => { this.operativeSystems = response['hydra:member']; }, error => { - console.error('Error fetching parent units:', error); + console.error('Error fetching operative systems:', error); } ); } private _filterSoftware(value: string): Observable { - - return this.softwareDataService.getSoftwareCollection({ 'name': value}).pipe( + return this.softwareDataService.getSoftwareCollection({ name: value }).pipe( map(response => response || []) ); } @@ -109,23 +119,6 @@ export class CreateSoftwareProfileComponent { this.softwareControl.setValue(''); } - load(): void { - this.dataService.getSoftwareProfile(this.data).subscribe({ - next: (response) => { - this.formGroup = this.fb.group({ - description: [response.description], - comments: [response.comments], - organizationalUnit: [response.organizationalUnit ? response.organizationalUnit['@id'] : null], - operativeSystem: [response.operativeSystem ? response.operativeSystem['@id'] : null], - }); - this.softwareProfileId = response['@id']; - }, - error: (err) => { - console.error('Error fetching software:', err); - } - }); - } - addSoftware() { const software = this.softwareCollection.find(s => s.id === this.selectedSoftware); if (software && !this.selectedSoftwares.includes(software)) { @@ -144,7 +137,6 @@ export class CreateSoftwareProfileComponent { onSubmit(): void { if (this.formGroup.valid) { - const payload = { description: this.formGroup.value.description, comments: this.formGroup.value.comments, @@ -155,24 +147,24 @@ export class CreateSoftwareProfileComponent { if (this.softwareProfileId) { this.http.put(`${this.baseUrl}${this.softwareProfileId}`, payload).subscribe( - (response) => { + () => { this.toastService.success('Software editado correctamente'); this.dialogRef.close(); }, (error) => { - this.toastService.error(error['error']['hydra:description']); - console.error('Error al editar el comando', error); + this.toastService.error(error.error['hydra:description']); + console.error('Error al editar el software', error); } ); } else { - this.http.post(`${this.baseUrl}/software-profiles`, payload).subscribe( - (response) => { + this.http.post(`${this.apiUrl}`, payload).subscribe( + () => { this.toastService.success('Software añadido correctamente'); this.dialogRef.close(); }, (error) => { - this.toastService.error(error['error']['hydra:description']); - console.error('Error al añadir comando', error); + this.toastService.error(error.error['hydra:description']); + console.error('Error al añadir software', error); } ); } diff --git a/ogWebconsole/src/app/components/software-profile/software-profile.component.html b/ogWebconsole/src/app/components/software-profile/software-profile.component.html index baa247e..d4ebd4a 100644 --- a/ogWebconsole/src/app/components/software-profile/software-profile.component.html +++ b/ogWebconsole/src/app/components/software-profile/software-profile.component.html @@ -1,11 +1,14 @@
-

Administrar perfiles software

+ +

Administrar perfiles software

- +
-
+
Buscar nombre de perfil @@ -13,7 +16,7 @@ Pulsar 'enter' para buscar
- +
- +
{{ column.header }} @@ -29,7 +32,7 @@ Acciones diff --git a/ogWebconsole/src/app/components/software-profile/software-profile.component.ts b/ogWebconsole/src/app/components/software-profile/software-profile.component.ts index 4034adb..ddf8d88 100644 --- a/ogWebconsole/src/app/components/software-profile/software-profile.component.ts +++ b/ogWebconsole/src/app/components/software-profile/software-profile.component.ts @@ -5,10 +5,10 @@ import {MatDialog} from "@angular/material/dialog"; import {HttpClient} from "@angular/common/http"; import {DataService} from "../software/data.service"; import {ToastrService} from "ngx-toastr"; -import {CreateSoftwareComponent} from "../software/create-software/create-software.component"; import {DeleteModalComponent} from "../../shared/delete_modal/delete-modal/delete-modal.component"; import {PageEvent} from "@angular/material/paginator"; import {CreateSoftwareProfileComponent} from "./create-software-profile/create-software-profile.component"; +import { JoyrideService } from 'ngx-joyride'; @Component({ selector: 'app-software-profile', @@ -58,7 +58,8 @@ export class SoftwareProfileComponent { public dialog: MatDialog, private http: HttpClient, private dataService: DataService, - private toastService: ToastrService + private toastService: ToastrService, + private joyrideService: JoyrideService ) {} ngOnInit(): void { @@ -90,7 +91,7 @@ export class SoftwareProfileComponent { editSoftware(softwareProfile: any): void { const dialogRef = this.dialog.open(CreateSoftwareProfileComponent, { width: '600px', - data: softwareProfile['@id'] + data: softwareProfile }); dialogRef.afterClosed().subscribe(result => { @@ -129,4 +130,12 @@ export class SoftwareProfileComponent { this.length = event.length; this.search(); } + + iniciarTour(): void { + this.joyrideService.startTour({ + steps: ['titleStep','addStep', 'filterStep', 'tableStep', 'actionsStep'], + showPrevButton: true, + themeColor: '#3f51b5' + }); + } } diff --git a/ogWebconsole/src/app/components/software/software.component.html b/ogWebconsole/src/app/components/software/software.component.html index 5f637fe..088df7f 100644 --- a/ogWebconsole/src/app/components/software/software.component.html +++ b/ogWebconsole/src/app/components/software/software.component.html @@ -1,11 +1,14 @@
-

Administrar Software

+ +

Administrar Software

- +
-
+
Buscar nombre de software @@ -21,7 +24,7 @@
- +
{{ column.header }} diff --git a/ogWebconsole/src/app/components/software/software.component.ts b/ogWebconsole/src/app/components/software/software.component.ts index 390dc49..1076b57 100644 --- a/ogWebconsole/src/app/components/software/software.component.ts +++ b/ogWebconsole/src/app/components/software/software.component.ts @@ -5,10 +5,10 @@ import {MatDialog} from "@angular/material/dialog"; import {HttpClient} from "@angular/common/http"; import {DataService} from "./data.service"; import {ToastrService} from "ngx-toastr"; -import {CreateCalendarComponent} from "../calendar/create-calendar/create-calendar.component"; import {DeleteModalComponent} from "../../shared/delete_modal/delete-modal/delete-modal.component"; import {PageEvent} from "@angular/material/paginator"; import {CreateSoftwareComponent} from "./create-software/create-software.component"; +import { JoyrideService } from 'ngx-joyride'; @Component({ selector: 'app-software', @@ -63,7 +63,8 @@ export class SoftwareComponent { public dialog: MatDialog, private http: HttpClient, private dataService: DataService, - private toastService: ToastrService + private toastService: ToastrService, + private joyrideService: JoyrideService ) {} ngOnInit(): void { @@ -134,4 +135,18 @@ export class SoftwareComponent { this.length = event.length; this.search(); } + + iniciarTour(): void { + this.joyrideService.startTour({ + steps: [ + 'titleStep', + 'addSoftwareStep', + 'searchStep', + 'tableStep', + ], + showPrevButton: true, + themeColor: '#3f51b5' + }); + } + } diff --git a/ogWebconsole/src/app/layout/header/header.component.html b/ogWebconsole/src/app/layout/header/header.component.html index 80bdc8a..051b347 100644 --- a/ogWebconsole/src/app/layout/header/header.component.html +++ b/ogWebconsole/src/app/layout/header/header.component.html @@ -1,17 +1,35 @@ - Opengnsys webconsole - + diff --git a/ogWebconsole/src/app/layout/sidebar/sidebar.component.html b/ogWebconsole/src/app/layout/sidebar/sidebar.component.html index 64c21aa..6db7503 100644 --- a/ogWebconsole/src/app/layout/sidebar/sidebar.component.html +++ b/ogWebconsole/src/app/layout/sidebar/sidebar.component.html @@ -1,51 +1,49 @@ - + Bienvenido {{username}} - + apartment Grupos - - - playlist_play + + + playlist_play Acciones - + chevron_right Comandos - + chevron_right Grupos - + chevron_right Tareas - - - + settings_ethernet DHCP @@ -54,23 +52,21 @@ - + analytics Estado - + lan Subredes - - - + desktop_windows Boot @@ -79,41 +75,40 @@ - + analytics Estado - + album ogLive - + assignment Plantillas PXE - + save Arranque PXE - - + calendar_month Calendarios - + terminal Software @@ -122,19 +117,19 @@ - + list - Listado + Listado - + folder_shared Perfiles - + terminal S. Operativos @@ -142,33 +137,31 @@ - + photo - imágenes + Imágenes - - - warehouse - Repositorios + + + warehouse + Repositorios - + list Menús - + search Buscar - -