diff --git a/ogWebconsole/src/app/components/groups/groups.component.ts b/ogWebconsole/src/app/components/groups/groups.component.ts index 4303a9c..7f54af6 100644 --- a/ogWebconsole/src/app/components/groups/groups.component.ts +++ b/ogWebconsole/src/app/components/groups/groups.component.ts @@ -147,15 +147,22 @@ export class GroupsComponent implements OnInit, OnDestroy { this.arrayClients = this.selectedClients.data; - const eventSource = new EventSource(`${this.mercureUrl}?topic=` - + encodeURIComponent(`clients`)); + const eventSource = new EventSource(`${this.mercureUrl}?topic=` + encodeURIComponent(`clients`)); eventSource.onmessage = (event) => { const data = JSON.parse(event.data); - if (data && data['@id']) { + + if (Array.isArray(data)) { + data.forEach((client) => { + if (client && client['@id']) { + this.updateClientStatus(client['@id'], client.status); + } + }); + } + else if (data && data['@id']) { this.updateClientStatus(data['@id'], data.status); } - } + }; this.clientFilterSubject.pipe(debounceTime(500)).subscribe(searchTerm => { this.filters['query'] = searchTerm; @@ -378,7 +385,7 @@ export class GroupsComponent implements OnInit, OnDestroy { this.selectedClients.data = response['hydra:member']; this.length = response['hydra:totalItems']; this.arrayClients = this.selectedClients.data; - this.hasClients = node.hasClients ?? false; + this.hasClients = this.selectedClients.data.length > 0; this.isLoadingClients = false; this.initialLoading = false; this.selection.clear(); diff --git a/ogWebconsole/src/app/components/repositories/repository-images/repository-images.component.css b/ogWebconsole/src/app/components/repositories/repository-images/repository-images.component.css deleted file mode 100644 index ecb91dd..0000000 --- a/ogWebconsole/src/app/components/repositories/repository-images/repository-images.component.css +++ /dev/null @@ -1,97 +0,0 @@ - -table { - width: 100%; -} - -.search-container { - display: flex; - justify-content: space-between; - align-items: center; - width: 100%; - margin: 1.5rem 0rem 1.5rem 0rem; - box-sizing: border-box; -} - -.search-string { - flex: 2; - padding: 5px; -} - -.search-boolean { - flex: 1; - padding: 5px; -} - -.header-container { - display: flex; - justify-content: space-between; - align-items: center; - padding: 10px 10px; - border-bottom: 1px solid #ddd; -} - -.mat-elevation-z8 { - box-shadow: 0px 0px 0px rgba(0,0,0,0.2); -} - -.paginator-container { - display: flex; - justify-content: end; - margin-bottom: 30px; -} - -.example-headers-align .mat-expansion-panel-header-description { - justify-content: space-between; - align-items: center; -} - -.example-headers-align .mat-mdc-form-field + .mat-mdc-form-field { - margin-left: 8px; -} - -.button-row { - display: table-cell; - max-width: 600px; -} - -.button-row .mat-mdc-button-base { - margin: 8px 8px 8px 0; -} - -.chip-failed { - background-color: #e87979 !important; - color: white; -} - -.chip-success { - background-color: #46c446 !important; - color: white; -} - -.chip-pending { - background-color: lightgrey !important; - color: black; -} - -.chip-in-progress { - background-color: #f5a623 !important; - color: white; -} - -.chip-transferring { - background-color: #f5a623 !important; - color: white; -} - -.header-container-title { - flex-grow: 1; - text-align: left; - margin-left: 1em; -} - -.images-button-row { - display: flex; - gap: 15px; - padding: 5px; -} - diff --git a/ogWebconsole/src/app/components/repositories/repository-images/repository-images.component.html b/ogWebconsole/src/app/components/repositories/repository-images/repository-images.component.html deleted file mode 100644 index e1f3c60..0000000 --- a/ogWebconsole/src/app/components/repositories/repository-images/repository-images.component.html +++ /dev/null @@ -1,104 +0,0 @@ - - -
- -
-

- {{ 'imagesTitle' | translate }} en {{ repository?.name }} -

-
-
- -
-
- -
-
- -
- - {{ 'searchLabel' | translate }} - - search - {{ 'searchHint' | translate }} - - - Estado - - Fallido - Pendiente - Transfiriendo - Creado con éxito - En progreso - Papelera - Creando archivos auxiliares - - -
- - - - - - - - - - - - - -
{{ column.header }} - - - {{ image.image[column.columnDef] ? 'check_circle' : 'cancel' }} - - - - - {{ getStatusLabel(image[column.columnDef]) }} - - - - {{ column.cell(image) }} - - Acciones - - - - - - - - - - - - -
- -
- - -
- diff --git a/ogWebconsole/src/app/components/repositories/repository-images/repository-images.component.spec.ts b/ogWebconsole/src/app/components/repositories/repository-images/repository-images.component.spec.ts deleted file mode 100644 index 064bad7..0000000 --- a/ogWebconsole/src/app/components/repositories/repository-images/repository-images.component.spec.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { provideHttpClient } from '@angular/common/http'; -import { provideHttpClientTesting } from '@angular/common/http/testing'; -import { ReactiveFormsModule, FormsModule, FormBuilder } from '@angular/forms'; -import { MatButtonModule } from '@angular/material/button'; -import { MatCheckboxModule } from '@angular/material/checkbox'; -import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; -import { MatFormFieldModule } from '@angular/material/form-field'; -import { MatInputModule } from '@angular/material/input'; -import { MatTableModule } from '@angular/material/table'; -import { MatPaginatorModule } from '@angular/material/paginator'; -import { MatDividerModule } from '@angular/material/divider'; -import { MatIconModule } from '@angular/material/icon'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { TranslateModule } from '@ngx-translate/core'; -import { ToastrModule, ToastrService } from 'ngx-toastr'; -import { JoyrideModule } from 'ngx-joyride'; -import { CommonModule } from '@angular/common'; -import {MatProgressSpinner} from "@angular/material/progress-spinner"; -import {RepositoryImagesComponent} from "./repository-images.component"; -import {LoadingComponent} from "../../../shared/loading/loading.component"; -import {MatOptionModule} from "@angular/material/core"; -import {MatSelectModule} from "@angular/material/select"; -import { ConfigService } from '@services/config.service'; - -describe('RepositoriesComponent', () => { - let component: RepositoryImagesComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - const mockConfigService = { - apiUrl: 'http://mock-api-url', - mercureUrl: 'http://mock-mercure-url' - }; - - await TestBed.configureTestingModule({ - declarations: [RepositoryImagesComponent, LoadingComponent], - imports: [ - ReactiveFormsModule, - FormsModule, - MatDialogModule, - MatFormFieldModule, - MatInputModule, - MatCheckboxModule, - MatButtonModule, - MatTableModule, - MatPaginatorModule, - MatDividerModule, - MatIconModule, - MatOptionModule, - BrowserAnimationsModule, - MatProgressSpinner, - MatSelectModule , - ToastrModule.forRoot(), - TranslateModule.forRoot(), - JoyrideModule.forRoot(), - CommonModule - ], - providers: [ - FormBuilder, - ToastrService, - provideHttpClient(), - provideHttpClientTesting(), - { - provide: MatDialogRef, - useValue: {} - }, - { - provide: MAT_DIALOG_DATA, - useValue: {} - }, - { provide: ConfigService, useValue: mockConfigService } - ] - }).compileComponents(); - - fixture = TestBed.createComponent(RepositoryImagesComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/ogWebconsole/src/app/components/repositories/repository-images/repository-images.component.ts b/ogWebconsole/src/app/components/repositories/repository-images/repository-images.component.ts deleted file mode 100644 index 5fde29f..0000000 --- a/ogWebconsole/src/app/components/repositories/repository-images/repository-images.component.ts +++ /dev/null @@ -1,362 +0,0 @@ -import {Component, Input, isDevMode, OnInit} from '@angular/core'; -import {MatTableDataSource} from "@angular/material/table"; -import {DatePipe} from "@angular/common"; -import {MatDialog} from "@angular/material/dialog"; -import {HttpClient} from "@angular/common/http"; -import {ToastrService} from "ngx-toastr"; -import {JoyrideService} from "ngx-joyride"; -import {Observable} from "rxjs"; -import {DeleteModalComponent} from "../../../shared/delete_modal/delete-modal/delete-modal.component"; -import {ExportImageComponent} from "../../images/export-image/export-image.component"; -import {BackupImageComponent} from "../backup-image/backup-image.component"; -import {ServerInfoDialogComponent} from "../../ogdhcp/server-info-dialog/server-info-dialog.component"; -import {ImportImageComponent} from "../import-image/import-image.component"; -import {ConvertImageComponent} from "../convert-image/convert-image.component"; -import { ConfigService } from '@services/config.service'; -import {Router} from "@angular/router"; - -@Component({ - selector: 'app-repository-images', - templateUrl: './repository-images.component.html', - styleUrl: './repository-images.component.css' -}) -export class RepositoryImagesComponent implements OnInit { - baseUrl: string; - private apiUrl: string; - dataSource = new MatTableDataSource(); - length: number = 0; - itemsPerPage: number = 10; - page: number = 0; - loading: boolean = false; - filters: { [key: string]: string } = {}; - alertMessage: string | null = null; - repository: any = {}; - datePipe: DatePipe = new DatePipe('es-ES'); - columns = [ - { - columnDef: 'id', - header: 'Id', - cell: (image: any) => `${image.id}` - }, - { - columnDef: 'name', - header: 'Nombre de imagen', - cell: (image: any) => `${image.image.name}` - }, - { - columnDef: 'remotePc', - header: 'Remote Pc', - cell: (image: any) => `${image.image?.remotePc}` - }, - { - columnDef: 'isGlobal', - header: 'Imagen global', - cell: (image: any) => `${image.image?.isGlobal}` - }, - { - columnDef: 'status', - header: 'Estado', - cell: (image: any) => `${image.status}` - }, - { - columnDef: 'imageFullsum', - header: 'Fullsum', - cell: (image: any) => `${image.imageFullsum}` - }, - { - columnDef: 'createdAt', - header: 'Fecha de creación', - cell: (image: any) => `${this.datePipe.transform(image.createdAt, 'dd/MM/yyyy hh:mm:ss')}` - } - ]; - displayedColumns = [...this.columns.map(column => column.columnDef), 'actions']; - - @Input() repositoryUuid: any - private repositoryId: any; - - constructor( - public dialog: MatDialog, - private http: HttpClient, - private toastService: ToastrService, - private joyrideService: JoyrideService, - private configService: ConfigService, - private router: Router, - ) { - this.baseUrl = this.configService.apiUrl; - this.apiUrl = `${this.baseUrl}/image-image-repositories`; - } - - ngOnInit(): void { - if (this.repositoryUuid) { - this.loadRepository() - } else { - this.search(); - } - } - - loadRepository(): void { - this.http.get(`${this.baseUrl}/image-repositories/${this.repositoryUuid}`, {}).subscribe( - data => { - this.repositoryId = data.id; - this.repository = data - this.search(); - }, - error => { - console.error('Error fetching image repositories', error); - } - ) - } - - getStatusLabel(status: string): string { - switch (status) { - case 'pending': - return 'Pendiente'; - case 'in-progress': - return 'En progreso'; - case 'aux-files-pending': - return 'Archivos auxiliares pendientes'; - case 'success': - return 'Creado con éxito'; - case 'trash': - return 'Papelera temporal'; - case 'failed': - return 'Fallido'; - case 'transferring': - return 'Transfiriendo'; - default: - return 'Estado desconocido'; - } - } - - search(): void { - this.loading = true; - this.http.get(`${this.apiUrl}?page=${this.page +1 }&itemsPerPage=${this.itemsPerPage}&repository.id=${this.repositoryId}`, { params: this.filters }).subscribe( - data => { - this.dataSource.data = data['hydra:member']; - this.length = data['hydra:totalItems']; - this.loading = false; - }, - error => { - console.error('Error fetching images', error); - this.loading = false; - } - ); - } - - onPageChange(event: any): void { - this.page = event.pageIndex; - this.itemsPerPage = event.pageSize; - this.length = event.length; - this.search(); - } - - loadImageAlert(image: any): Observable { - return this.http.get(`${this.apiUrl}/server/${image.uuid}/get`, {}); - } - - showImageInfo(event: MouseEvent, image:any) { - event.stopPropagation(); - this.loading = true; - this.loadImageAlert(image).subscribe( - response => { - this.alertMessage = response; - - this.dialog.open(ServerInfoDialogComponent, { - width: '800px', - data: { - message: this.alertMessage - } - }); - this.loading = false; - }, - error => { - this.toastService.error(error.error['hydra:description']); - this.loading = false; - } - ); - } - - importImage(): void { - this.dialog.open(ImportImageComponent, { - width: '600px', - data: { - repositoryUuid: this.repositoryUuid, - name: this.repository.name - } - }).afterClosed().subscribe((result) => { - if (result) { - this.search(); - } - }); - } - - convertImage(): void { - this.dialog.open(ConvertImageComponent, { - width: '600px', - data: { - repositoryUuid: this.repositoryUuid, - name: this.repository.name - } - }).afterClosed().subscribe((result) => { - if (result) { - this.search(); - } - }); - } - - toggleAction(image: any, action:string): void { - switch (action) { - case 'get-aux': - this.http.post(`${this.baseUrl}/image-image-repositories/server/${image.uuid}/create-aux-files`, {}).subscribe({ - next: (message) => { - this.toastService.success('Petición de creación de archivos auxiliares enviada'); - this.search() - }, - error: (error) => { - this.toastService.error(error.error['hydra:description']); - } - }); - break; - case 'delete-trash': - if (!image.imageFullsum) { - const dialogRef = this.dialog.open(DeleteModalComponent, { - width: '400px', - data: { name: image.name }, - }); - - dialogRef.afterClosed().subscribe((result) => { - this.http.delete(`${this.baseUrl}${image['@id']}`).subscribe({ - next: () => { - this.toastService.success('Image deleted successfully'); - this.search() - }, - error: (error) => { - this.toastService.error('Error deleting image'); - } - }); - }); - } else { - this.http.post(`${this.baseUrl}/image-image-repositories/server/${image.uuid}/delete-trash`, - { repository: `/image-repositories/${this.repositoryUuid}` }) - .subscribe({ - next: () => { - this.toastService.success('Petición de eliminación de la papelera temporal enviada'); - this.search() - }, - error: (error) => { - this.toastService.error(error.error['hydra:description']); - } - }); - } - - break; - case 'delete-permanent': - this.dialog.open(DeleteModalComponent, { - width: '300px', - data: { name: image.name }, - }).afterClosed().subscribe((result) => { - if (result) { - this.http.post(`${this.baseUrl}/image-image-repositories/server/${image.uuid}/delete-permanent`, {}).subscribe({ - next: () => { - this.toastService.success('Petición de eliminación de la papelera temporal enviada'); - this.search() - }, - error: (error) => { - this.toastService.error(error.error['hydra:description']); - } - }); - } - }); - break; - case 'recover': - this.http.post(`${this.baseUrl}/image-image-repositories/server/${image.uuid}/recover`, {}).subscribe({ - next: () => { - this.toastService.success('Petición de recuperación de la imagen enviada'); - this.search() - }, - error: (error) => { - this.toastService.error(error.error['hydra:description']); - } - }); - break; - case 'status': - this.http.post(`${this.baseUrl}/image-image-repositories/server/${image.uuid}/status`, {}).subscribe({ - next: (response: any) => { - this.toastService.info(response?.output); - this.search() - }, - error: (error) => { - this.toastService.error(error.error['hydra:description']); - } - }); - break; - case 'transfer': - this.http.get(`${this.baseUrl}${image.image['@id']}`).subscribe({ - next: (response) => { - this.dialog.open(ExportImageComponent, { - width: '600px', - data: { - image: response, - imageImageRepository: image - } - }); - }, - error: (error) => { - this.toastService.error(error.error['hydra:description']); - } - }); - break; - case 'transfer-global': - this.http.post(`${this.baseUrl}/image-image-repositories/server/${image.uuid}/transfer-global`, { - }).subscribe({ - next: (response) => { - this.toastService.success('Petición de exportación de imagen realizada correctamente'); - this.loading = false; - this.router.navigate(['/commands-logs']); - }, - error: error => { - this.loading = false; - this.toastService.error('Error en la petición de exportación de imagen'); - } - }); - break; - case 'backup': - this.http.get(`${this.baseUrl}${image.image['@id']}`).subscribe({ - next: (response) => { - this.dialog.open(BackupImageComponent, { - width: '600px', - data: { - image: response, - imageImageRepository: image - } - }); - }, - error: (error) => { - this.toastService.error(error.error['hydra:description']); - } - }); - break; - default: - console.error('Acción no soportada:', action); - break; - } - } - iniciarTour(): void { - this.joyrideService.startTour({ - steps: [ - 'imagesTitleStep', - 'addImageButton', - 'searchImagesField', - 'imagesTable', - 'actionsHeader', - 'editImageButton', - 'deleteImageButton', - 'imagesPagination' - ], - showPrevButton: true, - themeColor: '#3f51b5' - }); - } - - protected readonly isDevMode = isDevMode; -} diff --git a/ogWebconsole/src/assets/images/close-delete-remove-trash-cancel-cross-svgrepo-com.svg b/ogWebconsole/src/assets/images/close-delete-remove-trash-cancel-cross-svgrepo-com.svg new file mode 100644 index 0000000..1d3d548 --- /dev/null +++ b/ogWebconsole/src/assets/images/close-delete-remove-trash-cancel-cross-svgrepo-com.svg @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/ogWebconsole/src/assets/images/computer_disconnected.svg b/ogWebconsole/src/assets/images/computer_disconnected.svg new file mode 100644 index 0000000..e455b73 --- /dev/null +++ b/ogWebconsole/src/assets/images/computer_disconnected.svg @@ -0,0 +1,4 @@ + + + + diff --git a/ogWebconsole/src/assets/images/computer_initializing.svg b/ogWebconsole/src/assets/images/computer_initializing.svg index f0e2e65..152a739 100644 --- a/ogWebconsole/src/assets/images/computer_initializing.svg +++ b/ogWebconsole/src/assets/images/computer_initializing.svg @@ -1,3 +1,4 @@ - + + diff --git a/ogWebconsole/src/assets/images/ordenador_MNT.png b/ogWebconsole/src/assets/images/ordenador_MNT.png deleted file mode 100644 index 69da340..0000000 Binary files a/ogWebconsole/src/assets/images/ordenador_MNT.png and /dev/null differ diff --git a/ogWebconsole/src/assets/images/ordenador_busy.png b/ogWebconsole/src/assets/images/ordenador_busy.png deleted file mode 100644 index f010d84..0000000 Binary files a/ogWebconsole/src/assets/images/ordenador_busy.png and /dev/null differ diff --git a/ogWebconsole/src/assets/images/ordenador_initializing.png b/ogWebconsole/src/assets/images/ordenador_initializing.png deleted file mode 100644 index 6073601..0000000 Binary files a/ogWebconsole/src/assets/images/ordenador_initializing.png and /dev/null differ diff --git a/ogWebconsole/src/assets/images/ordenador_linux-session.png b/ogWebconsole/src/assets/images/ordenador_linux-session.png deleted file mode 100644 index 649eca7..0000000 Binary files a/ogWebconsole/src/assets/images/ordenador_linux-session.png and /dev/null differ diff --git a/ogWebconsole/src/assets/images/ordenador_linux.png b/ogWebconsole/src/assets/images/ordenador_linux.png deleted file mode 100644 index 3a7ae12..0000000 Binary files a/ogWebconsole/src/assets/images/ordenador_linux.png and /dev/null differ diff --git a/ogWebconsole/src/assets/images/ordenador_macos.png b/ogWebconsole/src/assets/images/ordenador_macos.png deleted file mode 100644 index 8816e0d..0000000 Binary files a/ogWebconsole/src/assets/images/ordenador_macos.png and /dev/null differ diff --git a/ogWebconsole/src/assets/images/ordenador_off.png b/ogWebconsole/src/assets/images/ordenador_off.png deleted file mode 100644 index 69da340..0000000 Binary files a/ogWebconsole/src/assets/images/ordenador_off.png and /dev/null differ diff --git a/ogWebconsole/src/assets/images/ordenador_turning-off.png b/ogWebconsole/src/assets/images/ordenador_turning-off.png deleted file mode 100644 index 69da340..0000000 Binary files a/ogWebconsole/src/assets/images/ordenador_turning-off.png and /dev/null differ diff --git a/ogWebconsole/src/assets/images/ordenador_windows-session.png b/ogWebconsole/src/assets/images/ordenador_windows-session.png deleted file mode 100644 index e45f574..0000000 Binary files a/ogWebconsole/src/assets/images/ordenador_windows-session.png and /dev/null differ diff --git a/ogWebconsole/src/assets/images/ordenador_windows.png b/ogWebconsole/src/assets/images/ordenador_windows.png deleted file mode 100644 index 107b4e0..0000000 Binary files a/ogWebconsole/src/assets/images/ordenador_windows.png and /dev/null differ diff --git a/ogWebconsole/src/assets/images/ordernador_og-live.png b/ogWebconsole/src/assets/images/ordernador_og-live.png deleted file mode 100644 index 3bc1ae1..0000000 Binary files a/ogWebconsole/src/assets/images/ordernador_og-live.png and /dev/null differ