I have improved progress bar when uploading files

This commit is contained in:
Rajnikant 2022-05-20 17:08:43 +05:30
parent f055836f44
commit 23fe8ae9b8
15 changed files with 221 additions and 15 deletions

View File

@ -277,6 +277,7 @@ import { LoggedUserComponent } from './components/users/logged-user/logged-user.
import { ImageManagerComponent } from './components/image-manager/image-manager.component';
import { AddImageDialogComponent } from './components/image-manager/add-image-dialog/add-image-dialog.component';
import { DeleteAllImageFilesDialogComponent } from './components/image-manager/deleteallfiles-dialog/deleteallfiles-dialog.component';
import { UploadingProcessbarComponent } from './common/uploading-processbar/uploading-processbar.component';
@NgModule({
declarations: [
@ -470,6 +471,7 @@ import { DeleteAllImageFilesDialogComponent } from './components/image-manager/d
ImageManagerComponent,
AddImageDialogComponent,
DeleteAllImageFilesDialogComponent,
UploadingProcessbarComponent,
],
imports: [
BrowserModule,

View File

@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { UploadServiceService } from './upload-service.service';
describe('UploadServiceService', () => {
let service: UploadServiceService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(UploadServiceService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@ -0,0 +1,23 @@
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class UploadServiceService {
private countSource = new BehaviorSubject(0);
currentCount = this.countSource.asObservable();
private cancelItem = new BehaviorSubject(false);
currentCancelItemDetails = this.cancelItem.asObservable();
constructor() { }
processBarCount(processCount:number) {
this.countSource.next(processCount)
}
cancelFileUploading(){
this.cancelItem.next(true)
}
}

View File

@ -0,0 +1,10 @@
<p>Image Uploading please wait .... {{uploadProgress}}%</p>
<div class="row proccessBar-row ">
<div class="col-md-9 proccessBar-col">
<mat-progress-bar mode="determinate" [value]="uploadProgress" aria-valuemin="0" aria-valuemax="100">
</mat-progress-bar>
</div>
<div class="col-md-3 proccessBar-col">
<button mat-button color="primary" (click)="cancelItem()" class="file-button">Cancel</button>
</div>
</div>

View File

@ -0,0 +1,11 @@
.mat-snack-bar-container{
min-width: 450px !important;
}
.proccessBar-row{
display: flex;
}
.proccessBar-col{
margin: auto;
}

View File

@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { UploadingProcessbarComponent } from './uploading-processbar.component';
describe('UploadingProcessbarComponent', () => {
let component: UploadingProcessbarComponent;
let fixture: ComponentFixture<UploadingProcessbarComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ UploadingProcessbarComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(UploadingProcessbarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,44 @@
import { Component, Inject, OnInit, Renderer2, ViewEncapsulation } from '@angular/core';
import { MatSnackBarRef, MAT_SNACK_BAR_DATA } from '@angular/material/snack-bar';
import { Subscription } from 'rxjs';
import { UploadServiceService } from './upload-service.service';
@Component({
selector: 'app-uploading-processbar',
templateUrl: './uploading-processbar.component.html',
styleUrls: ['./uploading-processbar.component.scss'],
encapsulation: ViewEncapsulation.None,
})
export class UploadingProcessbarComponent implements OnInit {
uploadProgress: number = 0
subscription: Subscription;
constructor(
@Inject(MAT_SNACK_BAR_DATA) public data,
private _snackRef: MatSnackBarRef<UploadingProcessbarComponent>,
private _US: UploadServiceService
) { }
ngOnInit() {
this.subscription = this._US.currentCount.subscribe((count) => {
this.uploadProgress = count;
if (this.uploadProgress === 100) {
this.dismiss()
}
})
}
dismiss() {
this._snackRef.dismiss();
}
cancelItem() {
this._US.cancelFileUploading()
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}

View File

@ -51,7 +51,7 @@
<div class="row">
<div class="col-md-12">
<div *ngIf="uploadedFile">
<mat-progress-bar mode="indeterminate" [value]="uploadProgress" aria-valuemin="0" aria-valuemax="100">
<mat-progress-bar mode="determinate" [value]="uploadProgress" aria-valuemin="0" aria-valuemax="100">
</mat-progress-bar>
</div>
</div>

View File

@ -1,4 +1,4 @@
import { Component, Inject, OnInit } from '@angular/core';
import { Component, DoCheck, 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';
@ -20,7 +20,7 @@ import { ImageData } from '../../../models/images';
],
})
export class AddImageDialogComponent implements OnInit {
export class AddImageDialogComponent implements OnInit,DoCheck {
server: Server;
uploadedFile: boolean = false;
isExistImage: boolean = false;
@ -28,7 +28,7 @@ export class AddImageDialogComponent implements OnInit {
install_appliance: boolean = false
selectFile: any = [];
uploadFileMessage: ImageData = []
uploadProgress:number = 0
constructor(
@Inject(MAT_DIALOG_DATA) public data: any,
public dialogRef: MatDialogRef<AddImageDialogComponent>,
@ -58,10 +58,19 @@ export class AddImageDialogComponent implements OnInit {
this.selectFile.forEach(imgElement => {
calls.push(this.imageService.uploadedImage(this.server, this.install_appliance, imgElement.name, imgElement).pipe(catchError(error => of(error))))
});
this.uploadProgress = calls.length
Observable.forkJoin(calls).subscribe(responses => {
this.uploadFileMessage = responses
this.uploadedFile = false;
this.isExistImage = true;
});
}
ngDoCheck(){
setTimeout(() => {
if(this.uploadProgress < 95){
this.uploadProgress = this.uploadProgress + 1
}
}, 100000);
}
}

View File

@ -103,9 +103,7 @@
placeholder="Please enter name"
/>
</mat-form-field>
<div *ngIf="uploadedFile">
<mat-progress-bar mode="determinate" [value]="uploadProgress" aria-valuemin="0" aria-valuemax="100"></mat-progress-bar>
</div>
<!-- here removed the processbar and common processbar -->
</div>
</form>
</mat-step>

View File

@ -1,6 +1,9 @@
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { MatSnackBar } from '@angular/material/snack-bar';
import { ActivatedRoute, Router } from '@angular/router';
import { UploadServiceService } from '../../../../common/uploading-processbar/upload-service.service';
import { UploadingProcessbarComponent } from 'app/common/uploading-processbar/uploading-processbar.component';
import { FileItem, FileUploader, FileUploaderOptions, ParsedResponseHeaders } from 'ng2-file-upload';
import { v4 as uuid } from 'uuid';
import { Compute } from '../../../../models/compute';
@ -51,7 +54,9 @@ export class AddQemuVmTemplateComponent implements OnInit {
private formBuilder: FormBuilder,
private templateMocksService: TemplateMocksService,
private configurationService: QemuConfigurationService,
private computeService: ComputeService
private computeService: ComputeService,
private snackBar : MatSnackBar,
private uploadServiceService : UploadServiceService
) {
this.qemuTemplate = new QemuTemplate();
@ -91,6 +96,8 @@ export class AddQemuVmTemplateComponent implements OnInit {
this.uploader.onProgressItem = (progress: any) => {
this.uploadProgress = progress['progress'];
this.uploadServiceService.processBarCount(this.uploadProgress)
};
const server_id = this.route.snapshot.paramMap.get('server_id');
@ -117,6 +124,14 @@ export class AddQemuVmTemplateComponent implements OnInit {
this.consoleTypes = this.configurationService.getConsoleTypes();
});
this.uploadServiceService.currentCancelItemDetails.subscribe((isCancel) => {
if (isCancel) {
this.cancelUploading()
}
})
}
setServerType(serverType: string) {
@ -131,7 +146,7 @@ export class AddQemuVmTemplateComponent implements OnInit {
uploadImageFile(event) {
this.uploadedFile = true;
// this.uploadedFile = true;
let name = event.target.files[0].name;
this.diskForm.controls['fileName'].setValue(name);
@ -142,7 +157,13 @@ export class AddQemuVmTemplateComponent implements OnInit {
if ((itemToUpload as any).options) (itemToUpload as any).options.disableMultipart = true; ((itemToUpload as any).options.headers =[{name:'Authorization',value:'Bearer ' + this.server.authToken}])
this.uploader.uploadItem(itemToUpload);
this.snackBar.openFromComponent(UploadingProcessbarComponent,{panelClass: 'uplaoding-file-snackabar',});
}
cancelUploading() {
this.uploader.clearQueue();
this.uploadServiceService.processBarCount(100)
this.toasterService.warning('Image Uploading canceled');
}
goBack() {
@ -171,4 +192,6 @@ export class AddQemuVmTemplateComponent implements OnInit {
this.toasterService.error(`Fill all required fields`);
}
}
}

View File

@ -154,7 +154,7 @@
>
<mat-icon aria-label="Refresh list of images">refresh</mat-icon></button
><br />
<div>
<div>
<div *ngFor="let version of applianceToInstall.versions">
<div class="list-item">
<span>{{ applianceToInstall.name }} version {{ version.name }}</span>
@ -225,6 +225,7 @@
[uploader]="uploaderImage"
/>
<button class="button" mat-raised-button (click)="file2.click()">Import</button>
<button
class="button"
mat-raised-button

View File

@ -2,9 +2,11 @@ import { animate, state, style, transition, trigger } from '@angular/animations'
import { ChangeDetectorRef, Component, Input, OnInit, ViewChild } from '@angular/core';
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { MatPaginator } from '@angular/material/paginator';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Sort } from '@angular/material/sort';
import { MatStepper } from '@angular/material/stepper';
import { MatTableDataSource } from '@angular/material/table';
import { UploadingProcessbarComponent } from 'app/common/uploading-processbar/uploading-processbar.component';
import { FileItem, FileUploader, ParsedResponseHeaders } from 'ng2-file-upload';
import * as SparkMD5 from 'spark-md5';
import { v4 as uuid } from 'uuid';
@ -29,6 +31,7 @@ import { TemplateService } from '../../../services/template.service';
import { ToasterService } from '../../../services/toaster.service';
import { ApplianceInfoDialogComponent } from './appliance-info-dialog/appliance-info-dialog.component';
import { TemplateNameDialogComponent } from './template-name-dialog/template-name-dialog.component';
import { UploadServiceService } from '../../../common/uploading-processbar/upload-service.service';
@Component({
selector: 'app-new-template-dialog',
@ -75,6 +78,7 @@ export class NewTemplateDialogComponent implements OnInit {
private iouImages: Image[] = [];
private templates: Template[] = [];
uploadProgress: number = 0;
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
@ViewChild('stepper', { static: true }) stepper: MatStepper;
@ -92,7 +96,9 @@ export class NewTemplateDialogComponent implements OnInit {
public dialog: MatDialog,
private computeService: ComputeService,
private changeDetectorRef: ChangeDetectorRef,
private progressService: ProgressService
private progressService: ProgressService,
public snackBar: MatSnackBar,
private uploadServiceService: UploadServiceService
) { }
ngOnInit() {
@ -195,6 +201,18 @@ export class NewTemplateDialogComponent implements OnInit {
this.uploaderImage.clearQueue();
};
this.uploaderImage.onProgressItem = (progress: any) => {
this.uploadProgress = progress['progress'];
this.uploadServiceService.processBarCount(this.uploadProgress)
};
this.uploadServiceService.currentCancelItemDetails.subscribe((isCancel) => {
if (isCancel) {
this.cancelUploading()
}
})
}
updateAppliances() {
@ -213,7 +231,6 @@ export class NewTemplateDialogComponent implements OnInit {
}
refreshImages() {
this.qemuService.getImages(this.server).subscribe((qemuImages) => {
this.qemuImages = qemuImages;
});
@ -353,8 +370,9 @@ export class NewTemplateDialogComponent implements OnInit {
dialogRef.componentInstance.appliance = object;
}
importImage(event, imageName) {
this.progressService.activate();
this.computeChecksumMd5(event.target.files[0], false).then((output) => {
let imageToInstall = this.applianceToInstall.images.filter((n) => n.filename === imageName)[0];
@ -371,12 +389,14 @@ export class NewTemplateDialogComponent implements OnInit {
dialogRef.afterClosed().subscribe((answer: boolean) => {
if (answer) {
this.importImageFile(event);
this.openSnackBar()
} else {
this.uploaderImage.clearQueue();
}
});
} else {
this.importImageFile(event);
this.openSnackBar()
}
});
}
@ -400,12 +420,17 @@ export class NewTemplateDialogComponent implements OnInit {
if ((itemToUpload as any).options) (itemToUpload as any).options.disableMultipart = true; ((itemToUpload as any).options.headers = [{ name: 'Authorization', value: 'Bearer ' + this.server.authToken }])
this.uploaderImage.uploadItem(itemToUpload);
this.progressService.activate();
};
fileReader.readAsText(file);
}
cancelUploading() {
this.uploaderImage.clearQueue();
this.uploadServiceService.processBarCount(100)
this.toasterService.warning('Image imported canceled');
}
checkImageFromVersion(image: string): boolean {
let imageToInstall = this.applianceToInstall.images.filter((n) => n.filename === image)[0];
if (this.applianceToInstall.qemu) {
@ -510,7 +535,6 @@ export class NewTemplateDialogComponent implements OnInit {
dialogRef.afterClosed().subscribe((answer: string) => {
if (answer) {
iouTemplate.name = answer;
this.iouService.addTemplate(this.server, iouTemplate).subscribe((template) => {
this.templateService.newTemplateCreated.next(template);
this.toasterService.success('Template added');
@ -697,6 +721,13 @@ export class NewTemplateDialogComponent implements OnInit {
processChunk(0);
});
}
openSnackBar() {
this.snackBar.openFromComponent(UploadingProcessbarComponent, {
panelClass: 'uplaoding-file-snackabar',
});
}
}
function compareNames(a: string, b: string, isAsc: boolean) {

View File

@ -15,6 +15,14 @@ export class ImageManagerService {
return this.httpServer.get<Image[]>(server, '/images') as Observable<Image[]>;
}
getImagePath(server:Server, install_appliance, image_path){
return `${server.protocol}//${server.host}:${server.port}/v3/images/upload/${image_path}?install_appliances=${install_appliance}`;
}
getUploadPath(server: Server, emulator: string, filename: string) {
return `${server.protocol}//${server.host}:${server.port}/v3/images/upload/${filename}`;
}
uploadedImage(server:Server, install_appliance, image_path, flie){
return this.httpServer.post<Image[]>(server, `/images/upload/${image_path}?install_appliances=${install_appliance}`,flie) as Observable<Image[]>;
}

View File

@ -14,6 +14,11 @@ a.table-link {
background: #0097a7 !important;
color: white !important;
}
.uplaoding-file-snackabar {
background: #263238 !important;
color: white !important;
max-width: 80% !important;
}
.snackbar-warning {
background: rgb(197, 199, 64) !important;