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 }}

+
+

{{ data.question }}

+
+
+ + +
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 @@
-
-

Image Manager

-
-
- -
+

Image Manager

+ + +
- -
+
@@ -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', {}); + } }