diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index b1f523be..1df168e3 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -31,7 +31,8 @@ import { ProgressComponent } from './common/progress/progress.component';
import { ProgressService } from './common/progress/progress.service';
import { AdbutlerComponent } from './components/adbutler/adbutler.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 { DrawingAddedComponent } from './components/drawings-listeners/drawing-added/drawing-added.component';
import { DrawingDraggedComponent } from './components/drawings-listeners/drawing-dragged/drawing-dragged.component';
@@ -511,6 +512,7 @@ import { DeleteResourceConfirmationDialogComponent } from './components/resource
ReadmeEditorComponent,
MarkedDirective,
InformationDialogComponent,
+ QuestionDialogComponent,
TemplateNameDialogComponent,
ConfigureCustomAdaptersDialogComponent,
EditNetworkConfigurationDialogComponent,
diff --git a/src/app/components/dialogs/information-dialog.component.html b/src/app/components/dialogs/information-dialog/information-dialog.component.html
similarity index 100%
rename from src/app/components/dialogs/information-dialog.component.html
rename to src/app/components/dialogs/information-dialog/information-dialog.component.html
diff --git a/src/app/components/dialogs/information-dialog.component.scss b/src/app/components/dialogs/information-dialog/information-dialog.component.scss
similarity index 100%
rename from src/app/components/dialogs/information-dialog.component.scss
rename to src/app/components/dialogs/information-dialog/information-dialog.component.scss
diff --git a/src/app/components/dialogs/information-dialog.component.ts b/src/app/components/dialogs/information-dialog/information-dialog.component.ts
similarity index 100%
rename from src/app/components/dialogs/information-dialog.component.ts
rename to src/app/components/dialogs/information-dialog/information-dialog.component.ts
diff --git a/src/app/components/dialogs/question-dialog/question-dialog.component.html b/src/app/components/dialogs/question-dialog/question-dialog.component.html
new file mode 100644
index 00000000..dae4a03a
--- /dev/null
+++ b/src/app/components/dialogs/question-dialog/question-dialog.component.html
@@ -0,0 +1,8 @@
+
{{ data.title }}
+
+
+
+
+
diff --git a/src/app/components/dialogs/question-dialog/question-dialog.component.scss b/src/app/components/dialogs/question-dialog/question-dialog.component.scss
new file mode 100644
index 00000000..e69de29b
diff --git a/src/app/components/dialogs/question-dialog/question-dialog.component.ts b/src/app/components/dialogs/question-dialog/question-dialog.component.ts
new file mode 100644
index 00000000..93b4b970
--- /dev/null
+++ b/src/app/components/dialogs/question-dialog/question-dialog.component.ts
@@ -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,
+ @Inject(MAT_DIALOG_DATA) public data: { title: string, question: string}
+ ) {}
+
+ onNoClick(): void {
+ this.dialogRef.close(false);
+ }
+
+ onYesClick(): void {
+ this.dialogRef.close(true);
+ }
+}
diff --git a/src/app/components/image-manager/image-manager.component.html b/src/app/components/image-manager/image-manager.component.html
index daad9e15..21ca7393 100644
--- a/src/app/components/image-manager/image-manager.component.html
+++ b/src/app/components/image-manager/image-manager.component.html
@@ -1,19 +1,19 @@
+
@@ -49,9 +49,9 @@
Image Size
{{ (row.image_size/1000000).toFixed()}} MB
-
+
-
+
@@ -67,4 +67,4 @@
-
\ No newline at end of file
+
diff --git a/src/app/components/image-manager/image-manager.component.scss b/src/app/components/image-manager/image-manager.component.scss
index 6eb9f60f..295185df 100644
--- a/src/app/components/image-manager/image-manager.component.scss
+++ b/src/app/components/image-manager/image-manager.component.scss
@@ -2,12 +2,22 @@
display: none;
}
-.img-btn{
- margin: auto;
- }
-.btn-box{
- display: flex;
- margin-top: 10px;
+.install-all-button {
+ height: 40px;
+ width: 160px;
+ margin: 20px;
+}
+
+.prune-button {
+ height: 40px;
+ width: 160px;
+ margin: 20px;
+}
+
+.add-button {
+ height: 40px;
+ width: 160px;
+ margin: 20px;
}
mat-header-cell, mat-cell {
@@ -21,4 +31,3 @@ mat-cell, mat-header-cell, mat-footer-cell {
min-height: inherit;
}
-
\ No newline at end of file
diff --git a/src/app/components/image-manager/image-manager.component.ts b/src/app/components/image-manager/image-manager.component.ts
index 94d9e1c7..ce688d44 100644
--- a/src/app/components/image-manager/image-manager.component.ts
+++ b/src/app/components/image-manager/image-manager.component.ts
@@ -6,12 +6,13 @@ import { ProgressService } from 'app/common/progress/progress.service';
import { Image } from '../../models/images';
import { Controller } from '../../models/controller';
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 { MatDialog } from '@angular/material/dialog';
import { ToasterService } from '../../services/toaster.service';
import { DeleteAllImageFilesDialogComponent } from './deleteallfiles-dialog/deleteallfiles-dialog.component';
import { imageDataSource, imageDatabase } from "./image-database-file";
+import { QuestionDialogComponent } from "@components/dialogs/question-dialog/question-dialog.component";
@Component({
selector: 'app-image-manager',
@@ -36,7 +37,6 @@ export class ImageManagerComponent implements OnInit {
private versionService: VersionService,
private dialog: MatDialog,
private toasterService: ToasterService,
-
) { }
ngOnInit(): void {
@@ -60,7 +60,6 @@ export class ImageManagerComponent implements OnInit {
},
(error) => {
this.toasterService.error(error.error.message)
-
}
);
}
@@ -100,6 +99,49 @@ export class ImageManagerComponent implements OnInit {
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() {
const dialogRef = this.dialog.open(AddImageDialogComponent, {
width: '600px',
diff --git a/src/app/components/project-map/new-template-dialog/new-template-dialog.component.ts b/src/app/components/project-map/new-template-dialog/new-template-dialog.component.ts
index dc7d7fd5..5b7b8082 100644
--- a/src/app/components/project-map/new-template-dialog/new-template-dialog.component.ts
+++ b/src/app/components/project-map/new-template-dialog/new-template-dialog.component.ts
@@ -11,7 +11,7 @@ import { FileItem, FileUploader, ParsedResponseHeaders } from 'ng2-file-upload';
import * as SparkMD5 from 'spark-md5';
import { v4 as uuid } from 'uuid';
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 { Project } from '../../../models/project';
import { QemuBinary } from '../../../models/qemu/qemu-binary';
diff --git a/src/app/services/image-manager.service.ts b/src/app/services/image-manager.service.ts
index 640ac5eb..087afa82 100644
--- a/src/app/services/image-manager.service.ts
+++ b/src/app/services/image-manager.service.ts
@@ -12,18 +12,27 @@ export class ImageManagerService {
constructor(private httpController: HttpController) { }
- getImages(controller:Controller ) {
+ getImages(controller: Controller) {
return this.httpController.get(controller, '/images') as Observable;
}
- 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}`;
}
- uploadedImage(controller :Controller, install_appliance, image_path, flie){
- return this.httpController.post(controller, `/images/upload/${image_path}?install_appliances=${install_appliance}`,flie) as Observable;
+ uploadedImage(controller: Controller, install_appliance, image_path, file){
+ return this.httpController.post(controller, `/images/upload/${image_path}?install_appliances=${install_appliance}`, file) as Observable;
}
- deleteFile(controller :Controller, image_path){
+
+ deleteFile(controller: Controller, image_path){
return this.httpController.delete(controller, `/images/${image_path}`) as Observable;
}
+
+ pruneImages(controller: Controller){
+ return this.httpController.delete(controller, '/images/prune');
+ }
+
+ installImages(controller: Controller) {
+ return this.httpController.post(controller, '/images/install', {});
+ }
}