refs #1693. Convert Image
parent
d2b3c8f772
commit
16c367e770
|
@ -129,6 +129,7 @@ import { AddClientsToSubnetComponent } from "./components/ogdhcp/add-clients-to-
|
||||||
import { ShowClientsComponent } from './components/ogdhcp/show-clients/show-clients.component';
|
import { ShowClientsComponent } from './components/ogdhcp/show-clients/show-clients.component';
|
||||||
import { OperationResultDialogComponent } from './components/ogdhcp/operation-result-dialog/operation-result-dialog.component';
|
import { OperationResultDialogComponent } from './components/ogdhcp/operation-result-dialog/operation-result-dialog.component';
|
||||||
import { ManageClientComponent } from './components/groups/shared/clients/manage-client/manage-client.component';
|
import { ManageClientComponent } from './components/groups/shared/clients/manage-client/manage-client.component';
|
||||||
|
import { ConvertImageComponent } from './components/repositories/convert-image/convert-image.component';
|
||||||
export function HttpLoaderFactory(http: HttpClient) {
|
export function HttpLoaderFactory(http: HttpClient) {
|
||||||
return new TranslateHttpLoader(http, './locale/', '.json');
|
return new TranslateHttpLoader(http, './locale/', '.json');
|
||||||
}
|
}
|
||||||
|
@ -213,7 +214,8 @@ export function HttpLoaderFactory(http: HttpClient) {
|
||||||
ManageOrganizationalUnitComponent,
|
ManageOrganizationalUnitComponent,
|
||||||
BackupImageComponent,
|
BackupImageComponent,
|
||||||
ShowClientsComponent,
|
ShowClientsComponent,
|
||||||
OperationResultDialogComponent
|
OperationResultDialogComponent,
|
||||||
|
ConvertImageComponent
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent],
|
bootstrap: [AppComponent],
|
||||||
imports: [BrowserModule,
|
imports: [BrowserModule,
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
.loading-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-form-field {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-dialog-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-list ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 8px;
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-item button {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
<h2 mat-dialog-title>Convertir imagene virtual hacia {{ data.name }}</h2>
|
||||||
|
|
||||||
|
<mat-dialog-content>
|
||||||
|
<mat-form-field appearance="fill" class="full-width">
|
||||||
|
<mat-label>Imagen</mat-label>
|
||||||
|
<input matInput [(ngModel)]="imageName" placeholder="Introduzca el nombre de la imagen a importar."
|
||||||
|
/>
|
||||||
|
<mat-hint>El nombre de la imagen tiene que ir con la extensión. </mat-hint>
|
||||||
|
</mat-form-field>
|
||||||
|
</mat-dialog-content>
|
||||||
|
|
||||||
|
<mat-dialog-actions>
|
||||||
|
<button class="ordinary-button" (click)="close()">Cancelar</button>
|
||||||
|
<button class="submit-button" (click)="save()">Continuar</button>
|
||||||
|
</mat-dialog-actions>
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ConvertImageComponent } from './convert-image.component';
|
||||||
|
|
||||||
|
describe('ConvertImageComponent', () => {
|
||||||
|
let component: ConvertImageComponent;
|
||||||
|
let fixture: ComponentFixture<ConvertImageComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ConvertImageComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(ConvertImageComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,50 @@
|
||||||
|
import {Component, Inject} from '@angular/core';
|
||||||
|
import {HttpClient} from "@angular/common/http";
|
||||||
|
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
||||||
|
import {ToastrService} from "ngx-toastr";
|
||||||
|
import {Router} from "@angular/router";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-convert-image',
|
||||||
|
templateUrl: './convert-image.component.html',
|
||||||
|
styleUrl: './convert-image.component.css'
|
||||||
|
})
|
||||||
|
export class ConvertImageComponent {
|
||||||
|
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
|
||||||
|
loading: boolean = true;
|
||||||
|
imageName: string = '';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private http: HttpClient,
|
||||||
|
public dialogRef: MatDialogRef<ConvertImageComponent>,
|
||||||
|
private toastService: ToastrService,
|
||||||
|
private router: Router,
|
||||||
|
@Inject(MAT_DIALOG_DATA) public data: { repositoryUuid: any, name: string }
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.loading = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
console.log(this.data?.repositoryUuid)
|
||||||
|
this.http.post<any>(`${this.baseUrl}/image-repositories/${this.data?.repositoryUuid}/convert-image`, {
|
||||||
|
name: this.imageName
|
||||||
|
}).subscribe({
|
||||||
|
next: (response) => {
|
||||||
|
this.toastService.success('Peticion de conversion de imagen enviada correctamente');
|
||||||
|
this.dialogRef.close();
|
||||||
|
this.router.navigate(['/commands-logs']);
|
||||||
|
},
|
||||||
|
error: error => {
|
||||||
|
this.toastService.error(error.error['hydra:description']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
this.dialogRef.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,25 +1,12 @@
|
||||||
<h2 mat-dialog-title>Importar imagenes a {{data.repository?.name}}</h2>
|
<h2 mat-dialog-title>Importar imagenes a {{ data.name }}</h2>
|
||||||
|
|
||||||
<mat-dialog-content>
|
<mat-dialog-content>
|
||||||
<mat-form-field appearance="fill" class="full-width">
|
<mat-form-field appearance="fill" class="full-width">
|
||||||
<mat-label>Seleccione imagenes a importar</mat-label>
|
<mat-label>Imagen</mat-label>
|
||||||
<mat-select [(value)]="selectedClients" multiple>
|
<input matInput [(ngModel)]="imageName" placeholder="Introduzca el nombre de la imagen a importar."
|
||||||
<mat-option *ngFor="let image of images" [value]="image['@id']">{{ image.name }}</mat-option>
|
/>
|
||||||
</mat-select>
|
<mat-hint>El nombre de la imagen tiene que ir sin la extensión. </mat-hint>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<div *ngIf="selectedClients.length > 0" class="selected-list">
|
|
||||||
<h3>Imágenes seleccionadas:</h3>
|
|
||||||
<ul>
|
|
||||||
<li *ngFor="let imageId of selectedClients" class="selected-item">
|
|
||||||
<span>{{ getImageName(imageId) }}</span>
|
|
||||||
<button mat-icon-button color="warn" (click)="removeImage(imageId)">
|
|
||||||
<mat-icon>delete</mat-icon>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</mat-dialog-content>
|
</mat-dialog-content>
|
||||||
|
|
||||||
<mat-dialog-actions>
|
<mat-dialog-actions>
|
||||||
|
|
|
@ -12,46 +12,26 @@ import {Router} from "@angular/router";
|
||||||
export class ImportImageComponent implements OnInit{
|
export class ImportImageComponent implements OnInit{
|
||||||
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
|
baseUrl: string = import.meta.env.NG_APP_BASE_API_URL;
|
||||||
loading: boolean = true;
|
loading: boolean = true;
|
||||||
images: any[] = [];
|
imageName: string = '';
|
||||||
selectedClients: any[] = [];
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private http: HttpClient,
|
private http: HttpClient,
|
||||||
public dialogRef: MatDialogRef<ImportImageComponent>,
|
public dialogRef: MatDialogRef<ImportImageComponent>,
|
||||||
private toastService: ToastrService,
|
private toastService: ToastrService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
@Inject(MAT_DIALOG_DATA) public data: { repository: any }
|
@Inject(MAT_DIALOG_DATA) public data: { repositoryUuid: any, name: string }
|
||||||
) {
|
) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
this.loadImages();
|
|
||||||
}
|
|
||||||
|
|
||||||
loadImages() {
|
|
||||||
this.http.get<any>(`${this.baseUrl}/images?page=1&itemsPerPage=50`).subscribe(
|
|
||||||
response => {
|
|
||||||
this.images = response['hydra:member'];
|
|
||||||
this.loading = false;
|
|
||||||
},
|
|
||||||
error => console.error('Error fetching organizational units:', error)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getImageName(imageId: string): string {
|
|
||||||
const image = this.images.find(img => img['@id'] === imageId);
|
|
||||||
return image ? image.name : 'Desconocido';
|
|
||||||
}
|
|
||||||
|
|
||||||
removeImage(imageId: string) {
|
|
||||||
this.selectedClients = this.selectedClients.filter(id => id !== imageId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
save() {
|
save() {
|
||||||
this.http.post<any>(`${this.baseUrl}${this.data.repository['@id']}/import-image`, {
|
console.log(this.data?.repositoryUuid)
|
||||||
images: this.selectedClients
|
this.http.post<any>(`${this.baseUrl}/image-repositories/${this.data?.repositoryUuid}/import-image`, {
|
||||||
|
name: this.imageName
|
||||||
}).subscribe({
|
}).subscribe({
|
||||||
next: (response) => {
|
next: (response) => {
|
||||||
this.toastService.success('Peticion de importacion de imagen enviada correctamente');
|
this.toastService.success('Peticion de importacion de imagen enviada correctamente');
|
||||||
|
@ -59,7 +39,7 @@ export class ImportImageComponent implements OnInit{
|
||||||
this.router.navigate(['/commands-logs']);
|
this.router.navigate(['/commands-logs']);
|
||||||
},
|
},
|
||||||
error: error => {
|
error: error => {
|
||||||
this.toastService.error('Error al importar imagenes');
|
this.toastService.error(error.error['hydra:description']);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,3 @@
|
||||||
.images-button-row {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-start;
|
|
||||||
margin-top: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
table {
|
table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -94,3 +89,9 @@ table {
|
||||||
margin-left: 1em;
|
margin-left: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.images-button-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 15px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,16 @@
|
||||||
{{ 'imagesTitle' | translate }} en {{ repository?.name }}
|
{{ 'imagesTitle' | translate }} en {{ repository?.name }}
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="images-button-row">
|
||||||
|
<button class="action-button" (click)="importImage()">
|
||||||
|
{{ 'importImageButton' | translate }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="images-button-row">
|
||||||
|
<button class="action-button" (click)="convertImage()">
|
||||||
|
{{ 'convertImageButton' | translate }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="search-container">
|
<div class="search-container">
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {Component, Input, OnInit} from '@angular/core';
|
import {Component, Input, isDevMode, OnInit} from '@angular/core';
|
||||||
import {MatTableDataSource} from "@angular/material/table";
|
import {MatTableDataSource} from "@angular/material/table";
|
||||||
import {DatePipe} from "@angular/common";
|
import {DatePipe} from "@angular/common";
|
||||||
import {MatDialog} from "@angular/material/dialog";
|
import {MatDialog} from "@angular/material/dialog";
|
||||||
|
@ -10,6 +10,8 @@ import {DeleteModalComponent} from "../../../shared/delete_modal/delete-modal/de
|
||||||
import {ExportImageComponent} from "../../images/export-image/export-image.component";
|
import {ExportImageComponent} from "../../images/export-image/export-image.component";
|
||||||
import {BackupImageComponent} from "../backup-image/backup-image.component";
|
import {BackupImageComponent} from "../backup-image/backup-image.component";
|
||||||
import {ServerInfoDialogComponent} from "../../ogdhcp/server-info-dialog/server-info-dialog.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";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-repository-images',
|
selector: 'app-repository-images',
|
||||||
|
@ -162,6 +164,34 @@ export class RepositoryImagesComponent implements OnInit {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
toggleAction(image: any, action:string): void {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case 'get-aux':
|
case 'get-aux':
|
||||||
|
@ -301,4 +331,6 @@ export class RepositoryImagesComponent implements OnInit {
|
||||||
themeColor: '#3f51b5'
|
themeColor: '#3f51b5'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected readonly isDevMode = isDevMode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -308,6 +308,8 @@
|
||||||
"noResultsMessage": "No results to display.",
|
"noResultsMessage": "No results to display.",
|
||||||
"imagesTitle": "Manage images",
|
"imagesTitle": "Manage images",
|
||||||
"addImageButton": "Add image",
|
"addImageButton": "Add image",
|
||||||
|
"importImageButton": "Import image",
|
||||||
|
"convertImageButton": "Convert virtual image",
|
||||||
"searchNameDescription": "Search images by name to quickly find a specific image.",
|
"searchNameDescription": "Search images by name to quickly find a specific image.",
|
||||||
"searchDefaultDescription": "Filter images to show only default or non-default images.",
|
"searchDefaultDescription": "Filter images to show only default or non-default images.",
|
||||||
"searchDefaultLabel": "Default image",
|
"searchDefaultLabel": "Default image",
|
||||||
|
|
|
@ -239,6 +239,8 @@
|
||||||
"organizationalUnitLabel": "Padre",
|
"organizationalUnitLabel": "Padre",
|
||||||
"ogLiveLabel": "OgLive",
|
"ogLiveLabel": "OgLive",
|
||||||
"imageNameLabel": "Nombre de la imagen",
|
"imageNameLabel": "Nombre de la imagen",
|
||||||
|
"importImageButton": "Importar imagen",
|
||||||
|
"convertImageButton": "Convertir imagen virtual",
|
||||||
"repositoryLabel": "Repositorios",
|
"repositoryLabel": "Repositorios",
|
||||||
"serialNumberLabel": "Número de Serie",
|
"serialNumberLabel": "Número de Serie",
|
||||||
"netifaceLabel": "Interfaz de red",
|
"netifaceLabel": "Interfaz de red",
|
||||||
|
|
Loading…
Reference in New Issue