mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-05-30 22:14:13 +00:00
Add prune images and install images to image manager
This commit is contained in:
parent
cd483e047b
commit
097efdcbcd
@ -31,7 +31,8 @@ import { ProgressComponent } from './common/progress/progress.component';
|
|||||||
import { ProgressService } from './common/progress/progress.service';
|
import { ProgressService } from './common/progress/progress.service';
|
||||||
import { AdbutlerComponent } from './components/adbutler/adbutler.component';
|
import { AdbutlerComponent } from './components/adbutler/adbutler.component';
|
||||||
import { BundledControllerFinderComponent } from './components/bundled-controller-finder/bundled-controller-finder.component';
|
import { BundledControllerFinderComponent } from './components/bundled-controller-finder/bundled-controller-finder.component';
|
||||||
import { InformationDialogComponent } from './components/dialogs/information-dialog.component';
|
import { InformationDialogComponent } from './components/dialogs/information-dialog/information-dialog.component';
|
||||||
|
import { QuestionDialogComponent } from "./components/dialogs/question-dialog/question-dialog.component";
|
||||||
import { DirectLinkComponent } from './components/direct-link/direct-link.component';
|
import { DirectLinkComponent } from './components/direct-link/direct-link.component';
|
||||||
import { DrawingAddedComponent } from './components/drawings-listeners/drawing-added/drawing-added.component';
|
import { DrawingAddedComponent } from './components/drawings-listeners/drawing-added/drawing-added.component';
|
||||||
import { DrawingDraggedComponent } from './components/drawings-listeners/drawing-dragged/drawing-dragged.component';
|
import { DrawingDraggedComponent } from './components/drawings-listeners/drawing-dragged/drawing-dragged.component';
|
||||||
@ -511,6 +512,7 @@ import { DeleteResourceConfirmationDialogComponent } from './components/resource
|
|||||||
ReadmeEditorComponent,
|
ReadmeEditorComponent,
|
||||||
MarkedDirective,
|
MarkedDirective,
|
||||||
InformationDialogComponent,
|
InformationDialogComponent,
|
||||||
|
QuestionDialogComponent,
|
||||||
TemplateNameDialogComponent,
|
TemplateNameDialogComponent,
|
||||||
ConfigureCustomAdaptersDialogComponent,
|
ConfigureCustomAdaptersDialogComponent,
|
||||||
EditNetworkConfigurationDialogComponent,
|
EditNetworkConfigurationDialogComponent,
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
<h1 mat-dialog-title>{{ data.title }}</h1>
|
||||||
|
<div mat-dialog-content>
|
||||||
|
<p>{{ data.question }}</p>
|
||||||
|
</div>
|
||||||
|
<div mat-dialog-actions>
|
||||||
|
<button mat-button (click)="onNoClick()">No</button>
|
||||||
|
<button mat-button (click)="onYesClick()">Yes</button>
|
||||||
|
</div>
|
@ -0,0 +1,21 @@
|
|||||||
|
import { Component, Inject } from '@angular/core';
|
||||||
|
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-question-dialog',
|
||||||
|
templateUrl: './question-dialog.component.html',
|
||||||
|
})
|
||||||
|
export class QuestionDialogComponent {
|
||||||
|
constructor(
|
||||||
|
public dialogRef: MatDialogRef<QuestionDialogComponent>,
|
||||||
|
@Inject(MAT_DIALOG_DATA) public data: { title: string, question: string}
|
||||||
|
) {}
|
||||||
|
|
||||||
|
onNoClick(): void {
|
||||||
|
this.dialogRef.close(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
onYesClick(): void {
|
||||||
|
this.dialogRef.close(true);
|
||||||
|
}
|
||||||
|
}
|
@ -1,19 +1,19 @@
|
|||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="default-header">
|
<div class="default-header">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-9">
|
<h1 class="col">Image Manager</h1>
|
||||||
<h1>Image Manager</h1>
|
<button mat-raised-button color="primary" (click)="installAllImages()" class="install-all-button">
|
||||||
</div>
|
<mat-icon>done_all</mat-icon> Install all images
|
||||||
<div class="col-md-3 btn-box">
|
</button>
|
||||||
<button class="img-btn" mat-button
|
<button mat-raised-button color="primary" (click)="pruneImages()" class="prune-button">
|
||||||
(click)="addImageDialog()">
|
<mat-icon>delete</mat-icon> Prune Images
|
||||||
<mat-icon>add</mat-icon> Add Image
|
</button>
|
||||||
</button>
|
<button mat-raised-button color="primary" (click)="addImageDialog()" class="add-button">
|
||||||
</div>
|
<mat-icon>add</mat-icon> Add Image
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="default-content">
|
<div class="default-content">
|
||||||
<app-controller-discovery></app-controller-discovery>
|
<app-controller-discovery></app-controller-discovery>
|
||||||
|
|
||||||
@ -49,9 +49,9 @@
|
|||||||
<mat-header-cell *matHeaderCellDef> Image Size </mat-header-cell>
|
<mat-header-cell *matHeaderCellDef> Image Size </mat-header-cell>
|
||||||
<mat-cell *matCellDef="let row"> {{ (row.image_size/1000000).toFixed()}} MB </mat-cell>
|
<mat-cell *matCellDef="let row"> {{ (row.image_size/1000000).toFixed()}} MB </mat-cell>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="delete" >
|
<ng-container matColumnDef="delete" >
|
||||||
<mat-header-cell *matHeaderCellDef>
|
<mat-header-cell *matHeaderCellDef>
|
||||||
<button mat-button *ngIf="(selection.hasValue() && isAllSelected()) || selection.selected.length > 1" (click)="deleteAllFiles()" aria-label="Example icon button with a delete icon">
|
<button mat-button *ngIf="(selection.hasValue() && isAllSelected()) || selection.selected.length > 1" (click)="deleteAllFiles()" aria-label="Example icon button with a delete icon">
|
||||||
<mat-icon>delete</mat-icon>
|
<mat-icon>delete</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
@ -67,4 +67,4 @@
|
|||||||
</mat-table>
|
</mat-table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,12 +2,22 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.img-btn{
|
.install-all-button {
|
||||||
margin: auto;
|
height: 40px;
|
||||||
}
|
width: 160px;
|
||||||
.btn-box{
|
margin: 20px;
|
||||||
display: flex;
|
}
|
||||||
margin-top: 10px;
|
|
||||||
|
.prune-button {
|
||||||
|
height: 40px;
|
||||||
|
width: 160px;
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-button {
|
||||||
|
height: 40px;
|
||||||
|
width: 160px;
|
||||||
|
margin: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-header-cell, mat-cell {
|
mat-header-cell, mat-cell {
|
||||||
@ -21,4 +31,3 @@ mat-cell, mat-header-cell, mat-footer-cell {
|
|||||||
min-height: inherit;
|
min-height: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -6,12 +6,13 @@ import { ProgressService } from 'app/common/progress/progress.service';
|
|||||||
import { Image } from '../../models/images';
|
import { Image } from '../../models/images';
|
||||||
import { Controller } from '../../models/controller';
|
import { Controller } from '../../models/controller';
|
||||||
import { ImageManagerService } from "../../services/image-manager.service";
|
import { ImageManagerService } from "../../services/image-manager.service";
|
||||||
import { DataSource, SelectionModel } from '@angular/cdk/collections';
|
import { SelectionModel } from '@angular/cdk/collections';
|
||||||
import { AddImageDialogComponent } from './add-image-dialog/add-image-dialog.component';
|
import { AddImageDialogComponent } from './add-image-dialog/add-image-dialog.component';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { ToasterService } from '../../services/toaster.service';
|
import { ToasterService } from '../../services/toaster.service';
|
||||||
import { DeleteAllImageFilesDialogComponent } from './deleteallfiles-dialog/deleteallfiles-dialog.component';
|
import { DeleteAllImageFilesDialogComponent } from './deleteallfiles-dialog/deleteallfiles-dialog.component';
|
||||||
import { imageDataSource, imageDatabase } from "./image-database-file";
|
import { imageDataSource, imageDatabase } from "./image-database-file";
|
||||||
|
import { QuestionDialogComponent } from "@components/dialogs/question-dialog/question-dialog.component";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-image-manager',
|
selector: 'app-image-manager',
|
||||||
@ -36,7 +37,6 @@ export class ImageManagerComponent implements OnInit {
|
|||||||
private versionService: VersionService,
|
private versionService: VersionService,
|
||||||
private dialog: MatDialog,
|
private dialog: MatDialog,
|
||||||
private toasterService: ToasterService,
|
private toasterService: ToasterService,
|
||||||
|
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
@ -60,7 +60,6 @@ export class ImageManagerComponent implements OnInit {
|
|||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
this.toasterService.error(error.error.message)
|
this.toasterService.error(error.error.message)
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -100,6 +99,49 @@ export class ImageManagerComponent implements OnInit {
|
|||||||
this.isAllDelete = true;
|
this.isAllDelete = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
installAllImages() {
|
||||||
|
const dialogRef = this.dialog.open(QuestionDialogComponent, {
|
||||||
|
width: '450px',
|
||||||
|
data: { title: 'Install all images', question: 'This will attempt to automatically create templates based on image checksums. Continue?'}
|
||||||
|
});
|
||||||
|
|
||||||
|
dialogRef.afterClosed().subscribe((result: boolean) => {
|
||||||
|
if (result) {
|
||||||
|
this.imageService.installImages(this.controller).subscribe(() => {
|
||||||
|
this.toasterService.success('Images installed');
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
this.toasterService.error(error.error.message)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pruneImages() {
|
||||||
|
const dialogRef = this.dialog.open(QuestionDialogComponent, {
|
||||||
|
width: '450px',
|
||||||
|
data: { title: 'Prune images', question: 'Delete all images not used by a template? This cannot be reverted.'}
|
||||||
|
});
|
||||||
|
|
||||||
|
dialogRef.afterClosed().subscribe((result: boolean) => {
|
||||||
|
if (result) {
|
||||||
|
this.imageService.pruneImages(this.controller).subscribe(
|
||||||
|
() => {
|
||||||
|
this.getImages()
|
||||||
|
this.unChecked()
|
||||||
|
this.toasterService.success('Images pruned');
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
this.getImages()
|
||||||
|
this.unChecked()
|
||||||
|
this.toasterService.error(error.error.message)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public addImageDialog() {
|
public addImageDialog() {
|
||||||
const dialogRef = this.dialog.open(AddImageDialogComponent, {
|
const dialogRef = this.dialog.open(AddImageDialogComponent, {
|
||||||
width: '600px',
|
width: '600px',
|
||||||
|
@ -11,7 +11,7 @@ import { FileItem, FileUploader, ParsedResponseHeaders } from 'ng2-file-upload';
|
|||||||
import * as SparkMD5 from 'spark-md5';
|
import * as SparkMD5 from 'spark-md5';
|
||||||
import { v4 as uuid } from 'uuid';
|
import { v4 as uuid } from 'uuid';
|
||||||
import { ProgressService } from '../../../common/progress/progress.service';
|
import { ProgressService } from '../../../common/progress/progress.service';
|
||||||
import { InformationDialogComponent } from '../../../components/dialogs/information-dialog.component';
|
import { InformationDialogComponent } from '../../../components/dialogs/information-dialog/information-dialog.component';
|
||||||
import { Appliance, Image, Version } from '../../../models/appliance';
|
import { Appliance, Image, Version } from '../../../models/appliance';
|
||||||
import { Project } from '../../../models/project';
|
import { Project } from '../../../models/project';
|
||||||
import { QemuBinary } from '../../../models/qemu/qemu-binary';
|
import { QemuBinary } from '../../../models/qemu/qemu-binary';
|
||||||
|
@ -12,18 +12,27 @@ export class ImageManagerService {
|
|||||||
|
|
||||||
constructor(private httpController: HttpController) { }
|
constructor(private httpController: HttpController) { }
|
||||||
|
|
||||||
getImages(controller:Controller ) {
|
getImages(controller: Controller) {
|
||||||
return this.httpController.get<Image[]>(controller, '/images') as Observable<Image[]>;
|
return this.httpController.get<Image[]>(controller, '/images') as Observable<Image[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
getImagePath(controller :Controller, install_appliance, image_path){
|
getImagePath(controller: Controller, install_appliance, image_path){
|
||||||
return `${controller.protocol}//${controller.host}:${controller.port}/${environment.current_version}/images/upload/${image_path}?install_appliances=${install_appliance}`;
|
return `${controller.protocol}//${controller.host}:${controller.port}/${environment.current_version}/images/upload/${image_path}?install_appliances=${install_appliance}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadedImage(controller :Controller, install_appliance, image_path, flie){
|
uploadedImage(controller: Controller, install_appliance, image_path, file){
|
||||||
return this.httpController.post<Image[]>(controller, `/images/upload/${image_path}?install_appliances=${install_appliance}`,flie) as Observable<Image[]>;
|
return this.httpController.post<Image[]>(controller, `/images/upload/${image_path}?install_appliances=${install_appliance}`, file) as Observable<Image[]>;
|
||||||
}
|
}
|
||||||
deleteFile(controller :Controller, image_path){
|
|
||||||
|
deleteFile(controller: Controller, image_path){
|
||||||
return this.httpController.delete<Image[]>(controller, `/images/${image_path}`) as Observable<Image[]>;
|
return this.httpController.delete<Image[]>(controller, `/images/${image_path}`) as Observable<Image[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pruneImages(controller: Controller){
|
||||||
|
return this.httpController.delete(controller, '/images/prune');
|
||||||
|
}
|
||||||
|
|
||||||
|
installImages(controller: Controller) {
|
||||||
|
return this.httpController.post(controller, '/images/install', {});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user