From c2410f093378b32092da58586bcc83107be3475f Mon Sep 17 00:00:00 2001 From: Rajnikant Date: Thu, 24 Mar 2022 17:28:42 +0530 Subject: [PATCH 1/5] Suspend a link or node show status change --- .../cartography/widgets/interface-status.ts | 4 ++-- src/app/cartography/widgets/link.ts | 24 ++++++++----------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/app/cartography/widgets/interface-status.ts b/src/app/cartography/widgets/interface-status.ts index ebafddcc..f699a50a 100644 --- a/src/app/cartography/widgets/interface-status.ts +++ b/src/app/cartography/widgets/interface-status.ts @@ -52,13 +52,13 @@ export class InterfaceStatusWidget implements Widget { new LinkStatus( start_point.x, start_point.y, - l.capturing && l.suspend ? 'suspended' : l.source.status, + !l.capturing && l.suspend ? 'suspended' : l.source.status, sourcePort ), new LinkStatus( end_point.x, end_point.y, - l.capturing && l.suspend ? 'suspended' : l.target.status, + !l.capturing && l.suspend ? 'suspended' : l.target.status, destinationPort ), ]; diff --git a/src/app/cartography/widgets/link.ts b/src/app/cartography/widgets/link.ts index 3e9a3334..150b38c7 100644 --- a/src/app/cartography/widgets/link.ts +++ b/src/app/cartography/widgets/link.ts @@ -22,7 +22,7 @@ export class LinkWidget implements Widget { private selectionManager: SelectionManager, private ethernetLinkWidget: EthernetLinkWidget, private serialLinkWidget: SerialLinkWidget - ) {} + ) { } public draw(view: SVGSelection) { const link_body = view.selectAll('g.link_body').data((l) => [l]); @@ -50,9 +50,8 @@ export class LinkWidget implements Widget { }) .attr('class', 'capture-icon') .attr('transform', (link) => { - return `translate (${(link.source.x + link.target.x) / 2 + 24}, ${ - (link.source.y + link.target.y) / 2 + 24 - }) scale(0.5)`; + return `translate (${(link.source.x + link.target.x) / 2 + 24}, ${(link.source.y + link.target.y) / 2 + 24 + }) scale(0.5)`; }) .attr('viewBox', '0 0 20 20') .append('image') @@ -74,9 +73,8 @@ export class LinkWidget implements Widget { }) .attr('class', 'filter-capture-icon') .attr('transform', (link) => { - return `translate (${(link.source.x + link.target.x) / 2 + 24}, ${ - (link.source.y + link.target.y) / 2 + 24 - }) scale(0.5)`; + return `translate (${(link.source.x + link.target.x) / 2 + 24}, ${(link.source.y + link.target.y) / 2 + 24 + }) scale(0.5)`; }) .attr('viewBox', '0 0 20 20') .append('image') @@ -99,9 +97,8 @@ export class LinkWidget implements Widget { .attr('width', '48px') .attr('height', '48px') .attr('transform', (link) => { - return `translate (${(link.source.x + link.target.x) / 2 + 24}, ${ - (link.source.y + link.target.y) / 2 + 24 - }) scale(0.5)`; + return `translate (${(link.source.x + link.target.x) / 2 + 24}, ${(link.source.y + link.target.y) / 2 + 24 + }) scale(0.5)`; }) .attr('viewBox', '0 0 20 20') .append('image') @@ -113,7 +110,7 @@ export class LinkWidget implements Widget { link_body .filter((l) => { return ( - l.capturing && + !l.capturing && l.suspend && !(l.filters.bpf || l.filters.corrupt || l.filters.delay || l.filters.frequency_drop || l.filters.packet_loss) ); @@ -125,9 +122,8 @@ export class LinkWidget implements Widget { }) .attr('class', 'pause-icon') .attr('transform', (link) => { - return `translate (${(link.source.x + link.target.x) / 2 + 24}, ${ - (link.source.y + link.target.y) / 2 + 24 - }) scale(0.5)`; + return `translate (${(link.source.x + link.target.x) / 2 + 24}, ${(link.source.y + link.target.y) / 2 + 24 + }) scale(0.5)`; }) .attr('viewBox', '0 0 20 20') .append('image') From 9558b2137f65a20fe632f616bce96b2deaa5eecd Mon Sep 17 00:00:00 2001 From: Rajnikant Date: Fri, 25 Mar 2022 11:34:55 +0530 Subject: [PATCH 2/5] Show the suspended status when we start a packet capture on the link. --- src/app/cartography/widgets/interface-status.ts | 4 ++-- src/app/cartography/widgets/link.ts | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/app/cartography/widgets/interface-status.ts b/src/app/cartography/widgets/interface-status.ts index f699a50a..6ed0e8dc 100644 --- a/src/app/cartography/widgets/interface-status.ts +++ b/src/app/cartography/widgets/interface-status.ts @@ -52,13 +52,13 @@ export class InterfaceStatusWidget implements Widget { new LinkStatus( start_point.x, start_point.y, - !l.capturing && l.suspend ? 'suspended' : l.source.status, + (( !l.capturing && l.suspend) || ( l.capturing && l.suspend)) ? 'suspended' : l.source.status, sourcePort ), new LinkStatus( end_point.x, end_point.y, - !l.capturing && l.suspend ? 'suspended' : l.target.status, + (( !l.capturing && l.suspend) || ( l.capturing && l.suspend)) ? 'suspended' : l.target.status, destinationPort ), ]; diff --git a/src/app/cartography/widgets/link.ts b/src/app/cartography/widgets/link.ts index 150b38c7..e5d56774 100644 --- a/src/app/cartography/widgets/link.ts +++ b/src/app/cartography/widgets/link.ts @@ -110,8 +110,7 @@ export class LinkWidget implements Widget { link_body .filter((l) => { return ( - !l.capturing && - l.suspend && + ((!l.capturing && l.suspend)|| l.capturing && l.suspend) && !(l.filters.bpf || l.filters.corrupt || l.filters.delay || l.filters.frequency_drop || l.filters.packet_loss) ); }) From 147cae13139543b4f7b7bf7d92068eeb3231061e Mon Sep 17 00:00:00 2001 From: Rajnikant Date: Tue, 5 Apr 2022 17:10:21 +0530 Subject: [PATCH 3/5] I completed enhancement work #1284 Image manager --- src/app/app-routing.module.ts | 2 + src/app/app.module.ts | 8 +- .../add-image-dialog.component.html | 27 +++ .../add-image-dialog.component.scss | 65 +++++++ .../add-image-dialog.component.spec.ts | 25 +++ .../add-image-dialog.component.ts | 70 +++++++ .../deleteallfiles-dialog.component.html | 19 ++ .../deleteallfiles-dialog.component.scss | 0 .../deleteallfiles-dialog.component.spec.ts | 25 +++ .../deleteallfiles-dialog.component.ts | 53 ++++++ .../image-manager.component.html | 69 +++++++ .../image-manager.component.scss | 22 +++ .../image-manager.component.spec.ts | 25 +++ .../image-manager/image-manager.component.ts | 177 ++++++++++++++++++ .../project-map/project-map.component.html | 4 + src/app/models/images.ts | 10 + .../services/image-manager.service.spec.ts | 16 ++ src/app/services/image-manager.service.ts | 23 +++ 18 files changed, 639 insertions(+), 1 deletion(-) create mode 100644 src/app/components/image-manager/add-image-dialog/add-image-dialog.component.html create mode 100644 src/app/components/image-manager/add-image-dialog/add-image-dialog.component.scss create mode 100644 src/app/components/image-manager/add-image-dialog/add-image-dialog.component.spec.ts create mode 100644 src/app/components/image-manager/add-image-dialog/add-image-dialog.component.ts create mode 100644 src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.html create mode 100644 src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.scss create mode 100644 src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.spec.ts create mode 100644 src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.ts create mode 100644 src/app/components/image-manager/image-manager.component.html create mode 100644 src/app/components/image-manager/image-manager.component.scss create mode 100644 src/app/components/image-manager/image-manager.component.spec.ts create mode 100644 src/app/components/image-manager/image-manager.component.ts create mode 100644 src/app/models/images.ts create mode 100644 src/app/services/image-manager.service.spec.ts create mode 100644 src/app/services/image-manager.service.ts diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 9b2b3650..b19c0c78 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -56,6 +56,7 @@ import { DefaultLayoutComponent } from './layouts/default-layout/default-layout. import { ServerResolve } from './resolvers/server-resolve'; import { UserManagementComponent } from './components/user-management/user-management.component'; import { LoggedUserComponent } from './components/users/logged-user/logged-user.component'; +import { ImageManagerComponent } from '@components/image-manager/image-manager.component'; const routes: Routes = [ { @@ -67,6 +68,7 @@ const routes: Routes = [ { path: 'bundled', component: BundledServerFinderComponent }, { path: 'server/:server_id/login', component: LoginComponent }, { path: 'server/:server_id/loggeduser', component: LoggedUserComponent }, + {path : 'server/:server_id/image-manager', component: ImageManagerComponent}, { path: 'server/:server_id/projects', component: ProjectsComponent, diff --git a/src/app/app.module.ts b/src/app/app.module.ts index caa42a53..6e33c169 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -272,6 +272,9 @@ import { HttpRequestsInterceptor } from './interceptors/http.interceptor'; import { UserManagementComponent } from './components/user-management/user-management.component' import { UserService } from './services/user.service'; import { LoggedUserComponent } from './components/users/logged-user/logged-user.component'; +import { ImageManagerComponent } from './components/image-manager/image-manager.component'; +import { AddImageDialogComponent } from './components/image-manager/add-image-dialog/add-image-dialog.component'; +import { DeleteallfilesDialogComponent } from './components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component'; @NgModule({ declarations: [ @@ -459,7 +462,10 @@ import { LoggedUserComponent } from './components/users/logged-user/logged-user. ConfigureCustomAdaptersDialogComponent, EditNetworkConfigurationDialogComponent, UserManagementComponent, - ProjectReadmeComponent + ProjectReadmeComponent, + ImageManagerComponent, + AddImageDialogComponent, + DeleteallfilesDialogComponent, ], imports: [ BrowserModule, diff --git a/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.html b/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.html new file mode 100644 index 00000000..867efe68 --- /dev/null +++ b/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.html @@ -0,0 +1,27 @@ +
+
+ Please Select Image + +
+
+ + +
+
+ +
+
+
+ {{i+1}}. {{img?.name}} +
+
+
+
+ + +
+
+
\ No newline at end of file diff --git a/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.scss b/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.scss new file mode 100644 index 00000000..48df4438 --- /dev/null +++ b/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.scss @@ -0,0 +1,65 @@ +.progress-bar { + padding: 0; + } + .progress { + width: 50px; + background-color: #263238; + height: 28px; + margin-left: 13px; + } + .mat-input-element { + font-size: medium; + font-weight: 200; + } + #fileInput { + position: absolute; + cursor: pointer; + z-index: 10; + opacity: 0; + height: 100%; + left: 0px; + top: 0px; + } + .mat-toolbar-single-row { + height: auto !important; + background: transparent; + padding: 0; + } + .mat-toolbar-single-row button { + width: 100px; + } + .mat-form-field { + width: 100%; + } + .message { + background-color: #ddd; + padding: 15px; + color: #333; + border: #aaa solid 1px; + border-radius: 4px; + margin: 15px 0; + } + .preview { + max-width: 200px; + vertical-align: middle; + } + .list-card { + margin-top: 20px; + } + .list-item { + margin-bottom: 20px; + } + + .non-visible { + display: none; + } + + mat-progress-bar{ + margin-top: 10px; + } + .txt-align{ + text-align: end; + + } + + \ No newline at end of file diff --git a/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.spec.ts b/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.spec.ts new file mode 100644 index 00000000..30885ae2 --- /dev/null +++ b/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AddImageDialogComponent } from './add-image-dialog.component'; + +describe('AddImageDialogComponent', () => { + let component: AddImageDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AddImageDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AddImageDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.ts b/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.ts new file mode 100644 index 00000000..679391c2 --- /dev/null +++ b/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.ts @@ -0,0 +1,70 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { animate, state, style, transition, trigger } from '@angular/animations'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { Server } from '../../../models/server'; +import { ImageManagerService } from '../../../services/image-manager.service'; +import { Observable } from 'rxjs'; + +@Component({ + selector: 'app-add-image-dialog', + templateUrl: './add-image-dialog.component.html', + styleUrls: ['./add-image-dialog.component.scss'], + animations: [ + trigger('detailExpand', [ + state('collapsed', style({ height: '0px', minHeight: '0', visibility: 'hidden' })), + state('expanded', style({ height: '*', visibility: 'visible' })), + transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')), + ]), + ], +}) + +export class AddImageDialogComponent implements OnInit { + server: Server; + uploadedFile: boolean = false; + uploadProgress: number = 0; + selectFile: any = []; + + + + constructor( + @Inject(MAT_DIALOG_DATA) public data: any, + public dialogRef: MatDialogRef, + private imageService: ImageManagerService, + + ) { } + + public ngOnInit(): void { + this.server = this.data + } + + async uploadImageFile(event) { + for (let imgFile of event.target.files) { + this.selectFile.push(imgFile) + } + + await this.upload().subscribe((_) => { + console.log(_) + this.dialogRef.close('file uploaded'); + }) + } + + // files uploading + upload() { + return new Observable(observe => { + this.selectFile.forEach((img, i) => { + let resCount = 1 + try { + resCount = resCount + i + this.uploadedFile = true; + this.imageService.uploadedImage(this.server, img.name, img) + .subscribe(() => { + this.selectFile.length == resCount ? observe.next() : '' + }, (error) => { + observe.error(error) + }) + } catch (error) { + } + }) + }) + } +} diff --git a/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.html b/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.html new file mode 100644 index 00000000..ad0e9cc2 --- /dev/null +++ b/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.html @@ -0,0 +1,19 @@ +
+

Do you want delete all files ?.

+
+

Your selected files

+

{{i+1}}. {{file?.filename}}

+
+
+ + +
+
+
+

Please wait.

+ +
+ + +
+
\ No newline at end of file diff --git a/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.scss b/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.spec.ts b/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.spec.ts new file mode 100644 index 00000000..96c8767d --- /dev/null +++ b/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DeleteallfilesDialogComponent } from './deleteallfiles-dialog.component'; + +describe('DeleteallfilesDialogComponent', () => { + let component: DeleteallfilesDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ DeleteallfilesDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DeleteallfilesDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.ts b/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.ts new file mode 100644 index 00000000..0be324f1 --- /dev/null +++ b/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.ts @@ -0,0 +1,53 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { ImageManagerService } from '@services/image-manager.service'; +import { ToasterService } from '@services/toaster.service'; +import { Observable } from 'rxjs'; + +@Component({ + selector: 'app-deleteallfiles-dialog', + templateUrl: './deleteallfiles-dialog.component.html', + styleUrls: ['./deleteallfiles-dialog.component.scss'] +}) +export class DeleteallfilesDialogComponent implements OnInit { + isDelete: boolean = false; + constructor( + @Inject(MAT_DIALOG_DATA) public deleteData: any, + public dialogRef: MatDialogRef, + private imageService: ImageManagerService, + private toasterService: ToasterService + ) { } + + ngOnInit(): void { + } + + async deleteAll() { + this.isDelete = true + await this.delete().subscribe((_) => { + this.dialogRef.close(true); + this.isDelete = false + }) + } + delete() { + return new Observable(observe => { + this.deleteData.deleteFilesPaths.forEach((_, i) => { + let imgDeleteCount = 1 + try { + imgDeleteCount = imgDeleteCount + i + this.imageService.deleteImage(this.deleteData.server, _.filename).subscribe( + () => { + this.deleteData.deleteFilesPaths.length === imgDeleteCount ? observe.next() : '' + }, + (error) => { + this.toasterService.error(error) + } + ); + } catch (error) { + this.toasterService.error(error) + } + }) + }) + } + + +} diff --git a/src/app/components/image-manager/image-manager.component.html b/src/app/components/image-manager/image-manager.component.html new file mode 100644 index 00000000..3d74edea --- /dev/null +++ b/src/app/components/image-manager/image-manager.component.html @@ -0,0 +1,69 @@ +
+
+
+
+

Image Manager

+
+
+ +
+
+ + +
+
+ + +
+ + + + + + + + + + + + + + + File Name + + {{ row.filename }} + + + + + Image Type + {{ row.image_type }} + + + + Image Size + {{ (row.image_size/1000000).toFixed()}} MB + + + + + + + + + + + + +
+
+
\ 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 new file mode 100644 index 00000000..23e34b24 --- /dev/null +++ b/src/app/components/image-manager/image-manager.component.scss @@ -0,0 +1,22 @@ +.non-visible { + display: none; + } + +.img-btn{ + margin: auto; + } +.btn-box{ + display: flex; + margin-top: 10px; +} + +.fb-btn{ + background-color: #263238 !important; + box-shadow: none !important; + height: 45px; +} +mat-header-cell, mat-cell { + justify-content: center; +} + + \ No newline at end of file diff --git a/src/app/components/image-manager/image-manager.component.spec.ts b/src/app/components/image-manager/image-manager.component.spec.ts new file mode 100644 index 00000000..257ce8f7 --- /dev/null +++ b/src/app/components/image-manager/image-manager.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ImageManagerComponent } from './image-manager.component'; + +describe('ImageManagerComponent', () => { + let component: ImageManagerComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ImageManagerComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ImageManagerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/image-manager/image-manager.component.ts b/src/app/components/image-manager/image-manager.component.ts new file mode 100644 index 00000000..31bd1867 --- /dev/null +++ b/src/app/components/image-manager/image-manager.component.ts @@ -0,0 +1,177 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { ServerService } from '../../services/server.service'; +import { VersionService } from '../../services/version.service'; +import { ProgressService } from 'app/common/progress/progress.service'; +import { Images } from '../../models/images'; +import { Server } from '../../models/server'; +import { ImageManagerService } from "../../services/image-manager.service"; +import { Version } from '../../models/version'; +import { DataSource, SelectionModel } from '@angular/cdk/collections'; +import { MatSort } from '@angular/material/sort'; +import { BehaviorSubject, Observable, Subscription, merge } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { AddImageDialogComponent } from './add-image-dialog/add-image-dialog.component'; +import { MatDialog } from '@angular/material/dialog'; +import { ToasterService } from '../../services/toaster.service'; +import { NotificationService } from '@services/notification.service'; +import { DeleteallfilesDialogComponent } from './deleteallfiles-dialog/deleteallfiles-dialog.component'; + +@Component({ + selector: 'app-image-manager', + templateUrl: './image-manager.component.html', + styleUrls: ['./image-manager.component.scss'] +}) +export class ImageManagerComponent implements OnInit { + server: Server; + public version: string; + dataSource: imageDataSource; + imageDatabase = new imageDatabase(); + isAllDelete: boolean = false + selection = new SelectionModel(true, []); + + displayedColumns = ['select', 'filename', 'image_type', 'image_size', 'delete']; + + constructor( + private imageService: ImageManagerService, + private progressService: ProgressService, + private route: ActivatedRoute, + private serverService: ServerService, + private versionService: VersionService, + private dialog: MatDialog, + private toasterService: ToasterService, + + ) { } + + ngOnInit(): void { + let server_id = parseInt(this.route.snapshot.paramMap.get('server_id')); + this.serverService.get(server_id).then((server: Server) => { + this.server = server; + if (server.authToken) { + this.getImages() + } + this.versionService.get(this.server).subscribe((version: Version) => { + this.version = version.version; + }); + }); + this.dataSource = new imageDataSource(this.imageDatabase); + } + + getImages() { + this.imageService.getSavedImgList(this.server).subscribe( + (images: Images[]) => { + this.imageDatabase.addImages(images) + }, + (error) => { + this.progressService.setError(error); + } + ); + } + + deleteFile(path) { + this.imageService.deleteImage(this.server, path).subscribe( + (res) => { + this.getImages() + this.unChecked() + this.toasterService.success('File deleted'); + }, + (error) => { + this.toasterService.error(error) + } + ); + } + + isAllSelected() { + const numSelected = this.selection.selected.length; + const numRows = this.imageDatabase.data.length; + return numSelected === numRows; + } + + masterToggle() { + this.isAllSelected() ? this.unChecked() : this.allChecked() + } + + unChecked() { + this.selection.clear() + this.isAllDelete = false + } + + allChecked() { + this.imageDatabase.data.forEach(row => this.selection.select(row)) + this.isAllDelete = true; + } + + public addImageDialog() { + console.log(this.server) + const dialogRef = this.dialog.open(AddImageDialogComponent, { + width: '750px', + maxHeight: '550px', + autoFocus: false, + disableClose: true, + data: this.server + }); + + dialogRef.afterClosed().subscribe((answer: string) => { + if (answer) { + this.getImages() + this.toasterService.success('File added'); + } else { + return false; + } + }); + } + + deleteAllFiles() { + console.log(this.server) + const dialogRef = this.dialog.open(DeleteallfilesDialogComponent, { + width: '400px', + maxHeight: '350px', + autoFocus: false, + disableClose: true, + data: { + server: this.server, + deleteFilesPaths: this.imageDatabase.data + } + }); + + dialogRef.afterClosed().subscribe((isAllfilesdeleted: boolean) => { + if (isAllfilesdeleted) { + this.unChecked() + this.getImages() + this.toasterService.success('All files deleted'); + } else { + return false; + } + }); + + } +} + +export class imageDatabase { + dataChange: BehaviorSubject = new BehaviorSubject([]); + get data(): Images[] { + return this.dataChange.value; + } + + public addImages(fliesData: Images[]) { + this.dataChange.next(fliesData); + } + +} + +export class imageDataSource extends DataSource { + constructor(private serverDatabase: imageDatabase) { + super(); + } + + connect(): Observable { + return merge(this.serverDatabase.dataChange).pipe( + map(() => { + return this.serverDatabase.data; + }) + ); + } + + disconnect() { } +} + diff --git a/src/app/components/project-map/project-map.component.html b/src/app/components/project-map/project-map.component.html index 000f83de..fa9a4852 100644 --- a/src/app/components/project-map/project-map.component.html +++ b/src/app/components/project-map/project-map.component.html @@ -103,6 +103,10 @@ settings Go to settings + - -
- -
- -
- {{i+1}}. {{img?.name}} -
-
-
-
- - +
+
+
+
Would you like to automatically install appliances for this image?
+
+
+
+ +
+ + + Yes + + + No + + +
+
+ +
+
+ + + + +
+
+
+
Please Select image
+ +
+
+ + +
+
+ +
+
+
+ {{i+1}}. {{img?.name}} +
+
+
+
+ + +
+
+
+
+
+
+
+

Uploaded image details

+

{{i+1}}. {{uploadFile?.filename ?? uploadFile?.error?.message}}

+
+
+
+ +
\ No newline at end of file diff --git a/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.scss b/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.scss index 48df4438..26141499 100644 --- a/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.scss +++ b/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.scss @@ -21,7 +21,7 @@ top: 0px; } .mat-toolbar-single-row { - height: auto !important; + height: auto; background: transparent; padding: 0; } @@ -59,7 +59,25 @@ } .txt-align{ text-align: end; - } - + .uploaded-text{ + color: #0ca8c7; + font-size: 17px; + } + .uploaded-error-text{ + color: #d52435; + font-weight: 600; + } + + .choose-instal-appliance { + display: flex; + flex-direction: row; + margin: 15px 0px 11px 0px; + align-items: flex-start; + } + + .instal-appliances-button { + margin: 11px; + } + \ No newline at end of file diff --git a/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.spec.ts b/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.spec.ts index 30885ae2..cf51111b 100644 --- a/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.spec.ts +++ b/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.spec.ts @@ -1,14 +1,53 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { MatCheckboxModule } from '@angular/material/checkbox'; +import { MatDialog, MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { MatIconModule } from '@angular/material/icon'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatToolbarModule } from '@angular/material/toolbar'; +import { ImageManagerService } from 'app/services/image-manager.service'; +import { ServerService } from '../../../services/server.service'; +import { MockedServerService } from '../../../services/server.service.spec'; +import { of } from 'rxjs'; +import { Server } from '../../../models/server'; import { AddImageDialogComponent } from './add-image-dialog.component'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { ToasterService } from 'app/services/toaster.service'; +import { MockedToasterService } from 'app/services/toaster.service.spec'; + +export class MockedImageManagerService { + public getImages(server: Server) { + return of(); + } + +} describe('AddImageDialogComponent', () => { let component: AddImageDialogComponent; let fixture: ComponentFixture; + + let mockedServerService = new MockedServerService(); + let mockedImageManagerService = new MockedImageManagerService() + let mockedToasterService = new MockedToasterService() beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ AddImageDialogComponent ] + imports:[ + MatIconModule, + MatToolbarModule, + MatMenuModule, + MatCheckboxModule, + MatDialogModule + ], + providers: [ + { provide: ServerService, useValue: mockedServerService }, + { provide: ImageManagerService, useValue: mockedImageManagerService }, + { provide: MAT_DIALOG_DATA, useValue: {} }, + { provide: MatDialogRef, useValue: {} }, + { provide: ToasterService, useValue: mockedToasterService }, + ], + declarations: [ AddImageDialogComponent ], + schemas: [NO_ERRORS_SCHEMA], }) .compileComponents(); }); diff --git a/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.ts b/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.ts index 679391c2..456e23d5 100644 --- a/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.ts +++ b/src/app/components/image-manager/add-image-dialog/add-image-dialog.component.ts @@ -3,7 +3,9 @@ import { animate, state, style, transition, trigger } from '@angular/animations' import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; import { Server } from '../../../models/server'; import { ImageManagerService } from '../../../services/image-manager.service'; -import { Observable } from 'rxjs'; +import { Observable, of } from 'rxjs'; +import { catchError } from 'rxjs/operators'; +import { ImageData } from '../../../models/images'; @Component({ selector: 'app-add-image-dialog', @@ -21,10 +23,11 @@ import { Observable } from 'rxjs'; export class AddImageDialogComponent implements OnInit { server: Server; uploadedFile: boolean = false; - uploadProgress: number = 0; + isExistImage: boolean = false; + isInstallAppliance: boolean = false + install_appliance: boolean = false selectFile: any = []; - - + uploadFileMessage: ImageData = [] constructor( @Inject(MAT_DIALOG_DATA) public data: any, @@ -37,34 +40,28 @@ export class AddImageDialogComponent implements OnInit { this.server = this.data } + selectInstallApplianceOption(ev) { + this.install_appliance = ev.value + } + async uploadImageFile(event) { for (let imgFile of event.target.files) { this.selectFile.push(imgFile) } - - await this.upload().subscribe((_) => { - console.log(_) - this.dialogRef.close('file uploaded'); - }) + await this.upload() } // files uploading upload() { - return new Observable(observe => { - this.selectFile.forEach((img, i) => { - let resCount = 1 - try { - resCount = resCount + i - this.uploadedFile = true; - this.imageService.uploadedImage(this.server, img.name, img) - .subscribe(() => { - this.selectFile.length == resCount ? observe.next() : '' - }, (error) => { - observe.error(error) - }) - } catch (error) { - } - }) - }) + const calls = []; + this.uploadedFile = true; + this.selectFile.forEach(imgElement => { + calls.push(this.imageService.uploadedImage(this.server, this.install_appliance, imgElement.name, imgElement).pipe(catchError(error => of(error)))) + }); + Observable.forkJoin(calls).subscribe(responses => { + this.uploadFileMessage = responses + this.uploadedFile = false; + this.isExistImage = true; + }); } } diff --git a/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.html b/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.html index ad0e9cc2..72a4d605 100644 --- a/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.html +++ b/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.html @@ -1,6 +1,6 @@ -
+

Do you want delete all files ?.

-
+

Your selected files

{{i+1}}. {{file?.filename}}

@@ -9,11 +9,26 @@
-
+

Please wait.

+
+ +
+
+
+
Images can't be deleted because image used in one or more template.
+

{{i+1}}. {{message?.error?.message}}

+
+
+
{{fileNotDeleted.length}} Images deleted successfully.
+
+
+
+ +
\ No newline at end of file diff --git a/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.scss b/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.scss index e69de29b..f962e55b 100644 --- a/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.scss +++ b/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.scss @@ -0,0 +1,11 @@ +.delete-text{ + color: #0ca8c7; + font-size: 17px; + } + +.deleted-error-text{ + color: #d52435; + font-weight: 600; +} + + \ No newline at end of file diff --git a/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.spec.ts b/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.spec.ts index 96c8767d..43aea89c 100644 --- a/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.spec.ts +++ b/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.spec.ts @@ -1,20 +1,60 @@ +import { NO_ERRORS_SCHEMA } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { MatCheckboxModule } from '@angular/material/checkbox'; +import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { MatIconModule } from '@angular/material/icon'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatToolbarModule } from '@angular/material/toolbar'; +import { ToasterService } from 'app/services/toaster.service'; +import { MockedToasterService } from 'app/services/toaster.service.spec'; +import { Server } from 'http'; +import { of } from 'rxjs'; +import { ImageManagerService } from '../../../services/image-manager.service'; +import { ServerService } from '../../../services/server.service'; +import { MockedServerService } from '../../../services/server.service.spec'; +import { ImageManagerComponent } from '../image-manager.component'; -import { DeleteallfilesDialogComponent } from './deleteallfiles-dialog.component'; +import { DeleteAllImageFilesDialogComponent } from './deleteallfiles-dialog.component'; -describe('DeleteallfilesDialogComponent', () => { - let component: DeleteallfilesDialogComponent; - let fixture: ComponentFixture; +export class MockedImageManagerService { + public deleteALLFile(server: Server, image_path) { + return of(); + } +} + + describe('DeleteAllImageFilesDialogComponent', () => { + let component: DeleteAllImageFilesDialogComponent; + let fixture: ComponentFixture; + let mockedServerService = new MockedServerService(); + let mockedImageManagerService = new MockedImageManagerService() + let mockedToasterService = new MockedToasterService() beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ DeleteallfilesDialogComponent ] + imports: [ + MatIconModule, + MatToolbarModule, + MatMenuModule, + MatCheckboxModule, + MatDialogModule, + ], + providers: [ + { provide: ServerService, useValue: mockedServerService }, + { provide: ImageManagerService, useValue: mockedImageManagerService }, + { provide: MAT_DIALOG_DATA, useValue: {} }, + { provide: MatDialogRef, useValue: {} }, + { provide: ToasterService, useValue: mockedToasterService }, + + ], + declarations: [DeleteAllImageFilesDialogComponent, + ], + schemas: [NO_ERRORS_SCHEMA], }) - .compileComponents(); + .compileComponents(); }); beforeEach(() => { - fixture = TestBed.createComponent(DeleteallfilesDialogComponent); + fixture = TestBed.createComponent(DeleteAllImageFilesDialogComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.ts b/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.ts index 0be324f1..6fd33fca 100644 --- a/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.ts +++ b/src/app/components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component.ts @@ -1,19 +1,25 @@ import { Component, Inject, OnInit } from '@angular/core'; import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; -import { ImageManagerService } from '@services/image-manager.service'; -import { ToasterService } from '@services/toaster.service'; -import { Observable } from 'rxjs'; +import { ImageManagerService } from '../../../services/image-manager.service'; +import { ToasterService } from '../../../services/toaster.service'; +import { Observable, of } from 'rxjs'; +import { catchError } from 'rxjs/operators'; +import { ImageData } from '../../../models/images'; @Component({ selector: 'app-deleteallfiles-dialog', templateUrl: './deleteallfiles-dialog.component.html', styleUrls: ['./deleteallfiles-dialog.component.scss'] }) -export class DeleteallfilesDialogComponent implements OnInit { +export class DeleteAllImageFilesDialogComponent implements OnInit { isDelete: boolean = false; + isUsedFiles: boolean = false; + deleteFliesDetails: ImageData = [] + fileNotDeleted: ImageData = [] + constructor( @Inject(MAT_DIALOG_DATA) public deleteData: any, - public dialogRef: MatDialogRef, + public dialogRef: MatDialogRef, private imageService: ImageManagerService, private toasterService: ToasterService ) { } @@ -23,30 +29,21 @@ export class DeleteallfilesDialogComponent implements OnInit { async deleteAll() { this.isDelete = true - await this.delete().subscribe((_) => { - this.dialogRef.close(true); - this.isDelete = false - }) + await this.deleteFile() } - delete() { - return new Observable(observe => { - this.deleteData.deleteFilesPaths.forEach((_, i) => { - let imgDeleteCount = 1 - try { - imgDeleteCount = imgDeleteCount + i - this.imageService.deleteImage(this.deleteData.server, _.filename).subscribe( - () => { - this.deleteData.deleteFilesPaths.length === imgDeleteCount ? observe.next() : '' - }, - (error) => { - this.toasterService.error(error) - } - ); - } catch (error) { - this.toasterService.error(error) - } - }) - }) + + deleteFile() { + const calls = []; + this.deleteData.deleteFilesPaths.forEach(pathElement => { + calls.push(this.imageService.deleteFile(this.deleteData.server, pathElement.filename).pipe(catchError(error => of(error)))) + }); + Observable.forkJoin(calls).subscribe(responses => { + this.deleteFliesDetails = responses.filter(x => x !== null) + this.fileNotDeleted = responses.filter(x => x === null) + this.isUsedFiles = true; + this.isDelete = true + }); + } diff --git a/src/app/components/image-manager/image-database-file.ts b/src/app/components/image-manager/image-database-file.ts new file mode 100644 index 00000000..09415d7b --- /dev/null +++ b/src/app/components/image-manager/image-database-file.ts @@ -0,0 +1,36 @@ + + +import { DataSource, SelectionModel } from '@angular/cdk/collections'; +import { MatSort } from '@angular/material/sort'; +import { BehaviorSubject, Observable, Subscription, merge } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { Image } from '../../models/images'; + + +export class imageDatabase { + dataChange: BehaviorSubject = new BehaviorSubject([]); + get data(): Image[] { + return this.dataChange.value; + } + + public addImages(fileData: Image[]) { + this.dataChange.next(fileData); + } + +} + +export class imageDataSource extends DataSource { + constructor(private serverDatabase: imageDatabase) { + super(); + } + + connect(): Observable { + return merge(this.serverDatabase.dataChange).pipe( + map(() => { + return this.serverDatabase.data; + }) + ); + } + + disconnect() { } +} diff --git a/src/app/components/image-manager/image-manager.component.html b/src/app/components/image-manager/image-manager.component.html index 3d74edea..2cabdf60 100644 --- a/src/app/components/image-manager/image-manager.component.html +++ b/src/app/components/image-manager/image-manager.component.html @@ -21,7 +21,7 @@ - @@ -49,14 +49,15 @@ Image Size {{ (row.image_size/1000000).toFixed()}} MB + - - diff --git a/src/app/components/image-manager/image-manager.component.scss b/src/app/components/image-manager/image-manager.component.scss index 23e34b24..047a0ad8 100644 --- a/src/app/components/image-manager/image-manager.component.scss +++ b/src/app/components/image-manager/image-manager.component.scss @@ -10,11 +10,6 @@ margin-top: 10px; } -.fb-btn{ - background-color: #263238 !important; - box-shadow: none !important; - height: 45px; -} mat-header-cell, mat-cell { justify-content: center; } diff --git a/src/app/components/image-manager/image-manager.component.spec.ts b/src/app/components/image-manager/image-manager.component.spec.ts index 257ce8f7..bdba7db1 100644 --- a/src/app/components/image-manager/image-manager.component.spec.ts +++ b/src/app/components/image-manager/image-manager.component.spec.ts @@ -1,16 +1,74 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { MatCheckboxModule } from '@angular/material/checkbox'; +import { MatDialogModule } from '@angular/material/dialog'; +import { MatIconModule } from '@angular/material/icon'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatToolbarModule } from '@angular/material/toolbar'; +import { ImageManagerService } from 'app/services/image-manager.service'; +import { ServerService } from 'app/services/server.service'; +import { MockedServerService } from 'app/services/server.service.spec'; +import { of } from 'rxjs'; +import { Server } from '../../models/server'; import { ImageManagerComponent } from './image-manager.component'; +import { Image } from '../../models/images'; +import { ProgressService } from 'app/common/progress/progress.service'; +import { MockedProgressService } from '../project-map/project-map.component.spec'; +import { MockedActivatedRoute } from '../preferences/preferences.component.spec'; +import { ActivatedRoute } from '@angular/router'; +import { MockedVersionService } from '../../services/version.service.spec'; +import { VersionService } from 'app/services/version.service'; +import { ToasterService } from 'app/services/toaster.service'; +import { MockedToasterService } from 'app/services/toaster.service.spec'; + +export class MockedImageManagerService { + public getImages(server: Server) { + return of(); + } + + public deleteFile(server: Server, image_path) { + return of(); + } + +} describe('ImageManagerComponent', () => { let component: ImageManagerComponent; let fixture: ComponentFixture; + let mockedServerService = new MockedServerService(); + let mockedImageManagerService = new MockedImageManagerService() + let mockedProgressService = new MockedProgressService() + let mockedVersionService = new MockedVersionService() + let mockedToasterService = new MockedToasterService() + let activatedRoute = new MockedActivatedRoute().get(); + + beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ ImageManagerComponent ] + imports: [ + MatIconModule, + MatToolbarModule, + MatMenuModule, + MatCheckboxModule, + MatDialogModule + ], + providers: [ + { + provide: ActivatedRoute, + useValue: activatedRoute, + }, + { provide: ServerService, useValue: mockedServerService }, + { provide: ImageManagerService, useValue: mockedImageManagerService }, + { provide: ProgressService, useValue: mockedProgressService }, + { provide: VersionService, useValue: mockedVersionService }, + { provide: ToasterService, useValue: mockedToasterService }, + ], + declarations: [ImageManagerComponent], + schemas: [NO_ERRORS_SCHEMA], }) - .compileComponents(); + .compileComponents(); }); beforeEach(() => { @@ -22,4 +80,17 @@ describe('ImageManagerComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + + it('should call save images', () => { + spyOn(mockedImageManagerService, 'getImages').and.returnValue(of({} as Image)); + component.getImages() + expect(mockedImageManagerService.getImages).toHaveBeenCalled(); + }); + + it('should delete image', () => { + spyOn(mockedImageManagerService, 'deleteFile').and.returnValue(of({} as Image)); + component.deleteFile('image_path') + expect(mockedImageManagerService.deleteFile).toHaveBeenCalled(); + }); }); diff --git a/src/app/components/image-manager/image-manager.component.ts b/src/app/components/image-manager/image-manager.component.ts index 31bd1867..3ca680d7 100644 --- a/src/app/components/image-manager/image-manager.component.ts +++ b/src/app/components/image-manager/image-manager.component.ts @@ -1,21 +1,17 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { ServerService } from '../../services/server.service'; import { VersionService } from '../../services/version.service'; import { ProgressService } from 'app/common/progress/progress.service'; -import { Images } from '../../models/images'; +import { Image } from '../../models/images'; import { Server } from '../../models/server'; import { ImageManagerService } from "../../services/image-manager.service"; -import { Version } from '../../models/version'; import { DataSource, SelectionModel } from '@angular/cdk/collections'; -import { MatSort } from '@angular/material/sort'; -import { BehaviorSubject, Observable, Subscription, merge } from 'rxjs'; -import { map } from 'rxjs/operators'; import { AddImageDialogComponent } from './add-image-dialog/add-image-dialog.component'; import { MatDialog } from '@angular/material/dialog'; import { ToasterService } from '../../services/toaster.service'; -import { NotificationService } from '@services/notification.service'; -import { DeleteallfilesDialogComponent } from './deleteallfiles-dialog/deleteallfiles-dialog.component'; +import { DeleteAllImageFilesDialogComponent } from './deleteallfiles-dialog/deleteallfiles-dialog.component'; +import { imageDataSource, imageDatabase } from "./image-database-file"; @Component({ selector: 'app-image-manager', @@ -30,7 +26,7 @@ export class ImageManagerComponent implements OnInit { isAllDelete: boolean = false selection = new SelectionModel(true, []); - displayedColumns = ['select', 'filename', 'image_type', 'image_size', 'delete']; + displayedColumns = ['select', 'filename', 'image_type', 'image_size','delete']; constructor( private imageService: ImageManagerService, @@ -50,33 +46,36 @@ export class ImageManagerComponent implements OnInit { if (server.authToken) { this.getImages() } - this.versionService.get(this.server).subscribe((version: Version) => { - this.version = version.version; - }); + // this.versionService.get(this.server).subscribe((version: Version) => { + // this.version = version.version; + // }); }); this.dataSource = new imageDataSource(this.imageDatabase); } getImages() { - this.imageService.getSavedImgList(this.server).subscribe( - (images: Images[]) => { + this.imageService.getImages(this.server).subscribe( + (images: Image[]) => { this.imageDatabase.addImages(images) }, (error) => { - this.progressService.setError(error); + this.toasterService.error(error.error.message) + } ); } deleteFile(path) { - this.imageService.deleteImage(this.server, path).subscribe( + this.imageService.deleteFile(this.server, path).subscribe( (res) => { this.getImages() this.unChecked() this.toasterService.success('File deleted'); }, (error) => { - this.toasterService.error(error) + this.getImages() + this.unChecked() + this.toasterService.error(error.error.message) } ); } @@ -87,7 +86,7 @@ export class ImageManagerComponent implements OnInit { return numSelected === numRows; } - masterToggle() { + selectAllImages() { this.isAllSelected() ? this.unChecked() : this.allChecked() } @@ -102,30 +101,30 @@ export class ImageManagerComponent implements OnInit { } public addImageDialog() { - console.log(this.server) const dialogRef = this.dialog.open(AddImageDialogComponent, { - width: '750px', + width: '600px', maxHeight: '550px', autoFocus: false, disableClose: true, data: this.server }); - dialogRef.afterClosed().subscribe((answer: string) => { - if (answer) { + dialogRef.afterClosed().subscribe((isAddes: boolean) => { + if (isAddes) { this.getImages() - this.toasterService.success('File added'); + this.unChecked() } else { + this.getImages() + this.unChecked() return false; } }); } deleteAllFiles() { - console.log(this.server) - const dialogRef = this.dialog.open(DeleteallfilesDialogComponent, { - width: '400px', - maxHeight: '350px', + const dialogRef = this.dialog.open(DeleteAllImageFilesDialogComponent, { + width: '500px', + maxHeight: '650px', autoFocus: false, disableClose: true, data: { @@ -140,38 +139,11 @@ export class ImageManagerComponent implements OnInit { this.getImages() this.toasterService.success('All files deleted'); } else { + this.unChecked() + this.getImages() return false; } }); - } } -export class imageDatabase { - dataChange: BehaviorSubject = new BehaviorSubject([]); - get data(): Images[] { - return this.dataChange.value; - } - - public addImages(fliesData: Images[]) { - this.dataChange.next(fliesData); - } - -} - -export class imageDataSource extends DataSource { - constructor(private serverDatabase: imageDatabase) { - super(); - } - - connect(): Observable { - return merge(this.serverDatabase.dataChange).pipe( - map(() => { - return this.serverDatabase.data; - }) - ); - } - - disconnect() { } -} - diff --git a/src/app/models/images.ts b/src/app/models/images.ts index 7dd38477..11e10612 100644 --- a/src/app/models/images.ts +++ b/src/app/models/images.ts @@ -1,4 +1,4 @@ -export class Images { +export class Image { filename: string; path: string; image_type: string; @@ -7,4 +7,8 @@ export class Images { checksum_algorithm: string; created_at: string; updated_at: string; +} + +export class ImageData { + } \ No newline at end of file diff --git a/src/app/services/image-manager.service.spec.ts b/src/app/services/image-manager.service.spec.ts index 8cb560a6..c54c18a1 100644 --- a/src/app/services/image-manager.service.spec.ts +++ b/src/app/services/image-manager.service.spec.ts @@ -1,16 +1,60 @@ -import { TestBed } from '@angular/core/testing'; +import { HttpClient } from '@angular/common/http'; +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; +import { inject, TestBed } from '@angular/core/testing'; +import { AppTestingModule } from 'app/testing/app-testing/app-testing.module'; +import { Server } from '../models/server'; +import { HttpServer } from './http-server.service'; +import { getTestServer } from './testing'; import { ImageManagerService } from './image-manager.service'; +import { Image } from "../models/images"; describe('ImageManagerService', () => { - let service: ImageManagerService; + let httpClient: HttpClient; + let httpTestingController: HttpTestingController; + let httpServer: HttpServer; + let server: Server; beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(ImageManagerService); + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule, AppTestingModule], + providers: [HttpServer, ImageManagerService], + }); + + httpClient = TestBed.get(HttpClient); + httpTestingController = TestBed.get(HttpTestingController); + httpServer = TestBed.get(HttpServer); + server = getTestServer(); + // service = TestBed.inject(ImageManagerService); + }); + afterEach(() => { + httpTestingController.verify(); }); - it('should be created', () => { + + it('should be get Images', inject([ImageManagerService], (service: ImageManagerService) => { + service.getImages(server).subscribe(); + const req = httpTestingController.expectOne('http://127.0.0.1:3080/v3/images'); + expect(req.request.method).toEqual('GET'); expect(service).toBeTruthy(); - }); + })); + + it('should add image', inject([ImageManagerService], (service: ImageManagerService) => { + let install_appliance = true + const image: Image = { + filename: '', + path: '', + image_type: '', + image_size: 0, + checksum: '', + checksum_algorithm: '', + created_at: '', + updated_at: '', + }; + + service.uploadedImage(server, install_appliance, image.filename, image).subscribe(); + const req = httpTestingController.expectOne('http://127.0.0.1:3080/v3/images/upload/?install_appliances=true'); + expect(req.request.method).toEqual('POST'); + expect(req.request.body).toEqual(image); + })); }); diff --git a/src/app/services/image-manager.service.ts b/src/app/services/image-manager.service.ts index 5ad5aced..c69531b3 100644 --- a/src/app/services/image-manager.service.ts +++ b/src/app/services/image-manager.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@angular/core'; import { Server } from '../models/server'; import { HttpServer } from './http-server.service'; -import { merge, Observable, Subscription } from 'rxjs'; -import { Images } from "../models/images"; +import { Observable } from 'rxjs'; +import { Image } from "../models/images"; @Injectable({ providedIn: 'root' @@ -11,13 +11,14 @@ export class ImageManagerService { constructor(private httpServer: HttpServer) { } - getSavedImgList(server: Server) { - return this.httpServer.get(server, '/images') as Observable; + getImages(server: Server) { + return this.httpServer.get(server, '/images') as Observable; } - uploadedImage(server:Server, image_path, flie){ - return this.httpServer.post(server, `/images/upload/${image_path}?install_appliances=true`,flie) as Observable; + + uploadedImage(server:Server, install_appliance, image_path, flie){ + return this.httpServer.post(server, `/images/upload/${image_path}?install_appliances=${install_appliance}`,flie) as Observable; } - deleteImage(server:Server, image_path){ - return this.httpServer.delete(server, `/images/${image_path}`) as Observable; + deleteFile(server:Server, image_path){ + return this.httpServer.delete(server, `/images/${image_path}`) as Observable; } } From 258e9f02c2a995a525e1bb4fdb90443fff2e048e Mon Sep 17 00:00:00 2001 From: Rajnikant Date: Wed, 13 Apr 2022 15:58:10 +0530 Subject: [PATCH 5/5] Delete multiple images in one go if I select 2 or more images --- src/app/components/image-manager/image-manager.component.html | 2 +- src/app/components/image-manager/image-manager.component.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/components/image-manager/image-manager.component.html b/src/app/components/image-manager/image-manager.component.html index 2cabdf60..5dde19d3 100644 --- a/src/app/components/image-manager/image-manager.component.html +++ b/src/app/components/image-manager/image-manager.component.html @@ -52,7 +52,7 @@ - diff --git a/src/app/components/image-manager/image-manager.component.ts b/src/app/components/image-manager/image-manager.component.ts index 3ca680d7..ee51888f 100644 --- a/src/app/components/image-manager/image-manager.component.ts +++ b/src/app/components/image-manager/image-manager.component.ts @@ -129,7 +129,7 @@ export class ImageManagerComponent implements OnInit { disableClose: true, data: { server: this.server, - deleteFilesPaths: this.imageDatabase.data + deleteFilesPaths: this.selection.selected } });