Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NAS-133932 / 25.10 / Ease of use improvements for ISO uploads #11507

Merged
merged 6 commits into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {
ChangeDetectionStrategy, ChangeDetectorRef, Component, input, viewChild,
ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, input, viewChild,
} from '@angular/core';
import {
ControlValueAccessor, NgControl,
Expand Down Expand Up @@ -50,7 +50,7 @@ export class IxFileInputComponent implements ControlValueAccessor {

private onChange: (value: File[]) => void = (): void => {};
private onTouch: () => void = (): void => {};
private fileInput = viewChild.required<HTMLInputElement>('fileInput');
private fileInput = viewChild.required<ElementRef<HTMLInputElement>>('fileInput');

constructor(
public controlDirective: NgControl,
Expand All @@ -70,7 +70,7 @@ export class IxFileInputComponent implements ControlValueAccessor {
writeValue(value: File[] | null): void {
this.value = this.transformFiles(value || []);
if (!value?.length) {
this.fileInput().value = null;
this.fileInput().nativeElement.value = null;
}

this.cdr.markForCheck();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { createComponentFactory, mockProvider, Spectator } from '@ngneat/spectator/jest';
import { of } from 'rxjs';
import { fakeFile } from 'app/core/testing/utils/fake-file.uitls';
import { mockApi, mockCall } from 'app/core/testing/utils/mock-api.utils';
import { mockAuth } from 'app/core/testing/utils/mock-auth.utils';
import { Job } from 'app/interfaces/job.interface';
import { DialogService } from 'app/modules/dialog/dialog.service';
Expand All @@ -28,6 +29,9 @@ describe('UploadIsoButtonComponent', () => {
})),
}),
mockProvider(SnackbarService),
mockApi([
mockCall('virt.volume.query', []),
]),
mockAuth(),
],
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import {
import { FormControl, ReactiveFormsModule } from '@angular/forms';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { filter } from 'rxjs';
import { filter, map, switchMap } from 'rxjs';
import { RequiresRolesDirective } from 'app/directives/requires-roles/requires-roles.directive';
import { Role } from 'app/enums/role.enum';
import { DialogService } from 'app/modules/dialog/dialog.service';
import { IxFileInputComponent } from 'app/modules/forms/ix-forms/components/ix-file-input/ix-file-input.component';
import { SnackbarService } from 'app/modules/snackbar/services/snackbar.service';
import { ApiService } from 'app/modules/websocket/api.service';
import { ErrorHandlerService } from 'app/services/error-handler.service';
import { UploadService } from 'app/services/upload.service';

Expand Down Expand Up @@ -39,18 +40,21 @@ export class UploadIsoButtonComponent implements OnInit {
private translate: TranslateService,
private uploadService: UploadService,
private snackbar: SnackbarService,
private api: ApiService,
) {}

ngOnInit(): void {
this.imageFileControl.valueChanges
.pipe(
filter((files) => !!files?.length),
switchMap(() => this.api.call('virt.volume.query')),
map((volumes) => volumes.map((volume) => volume.name)),
untilDestroyed(this),
)
.subscribe(() => this.uploadImage());
.subscribe((existingNames) => this.uploadImage(existingNames));
}

private uploadImage(): void {
private uploadImage(existingNames: string[]): void {
const file = this.imageFileControl.value[0];
this.imageFileControl.setValue([]);
const job$ = this.uploadService.uploadAsJob({
Expand All @@ -62,6 +66,14 @@ export class UploadIsoButtonComponent implements OnInit {
}],
});

if (existingNames.includes(file.name)) {
this.dialogService.error({
title: this.translate.instant('Error'),
message: this.translate.instant('Volume with this name already exists.'),
});
return;
}

this.dialogService
.jobDialog(job$, { title: this.translate.instant('Uploading Image') })
.afterClosed()
Expand Down
32 changes: 23 additions & 9 deletions src/app/services/upload.service.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import {
HttpClient, HttpEvent, HttpRequest, HttpResponse,
HttpClient, HttpEvent, HttpProgressEvent, HttpRequest, HttpResponse,
} from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Store } from '@ngrx/store';
import { filter, Observable } from 'rxjs';
import { TranslateService } from '@ngx-translate/core';
import { Observable, of } from 'rxjs';
import { map, switchMap, take } from 'rxjs/operators';
import { JobState } from 'app/enums/job-state.enum';
import { observeJob } from 'app/helpers/operators/observe-job.operator';
import { ApiJobMethod, ApiJobResponse } from 'app/interfaces/api/api-job-directory.interface';
import { Job } from 'app/interfaces/job.interface';
Expand All @@ -24,6 +26,7 @@ export interface UploadOptions<M extends ApiJobMethod = ApiJobMethod> {
export class UploadService {
constructor(
protected http: HttpClient,
private translate: TranslateService,
private authService: AuthService,
private store$: Store<AppState>,
) {}
Expand Down Expand Up @@ -55,15 +58,26 @@ export class UploadService {
uploadAsJob<M extends ApiJobMethod>(options: UploadOptions<M>): Observable<Job<ApiJobResponse<M>>> {
return this.upload(options)
.pipe(
filter((event) => event instanceof HttpResponse),
switchMap((response: HttpResponse<{ job_id: number }>) => {
const jobId = response.body?.job_id;
if (!jobId) {
throw new Error('Job ID not found in response');
switchMap((response: HttpResponse<{ job_id: number }> | HttpProgressEvent) => {
if (response instanceof HttpResponse) {
const jobId = response.body?.job_id;
if (!jobId) {
throw new Error('Job ID not found in response');
}
return this.store$.select(selectJob(jobId))
.pipe(observeJob()) as Observable<Job<ApiJobResponse<M>>>;
}

return this.store$.select(selectJob(jobId))
.pipe(observeJob()) as Observable<Job<ApiJobResponse<M>>>;
const fakeJob: Job<ApiJobResponse<M>> = {
progress: {
percent: response.loaded && response.total ? response.loaded / response.total * 100 : 0,
description: this.translate.instant('Uploading'),
},
method: options.method,
state: JobState.Running,
} as Job<ApiJobResponse<M>>;

return of(fakeJob);
}),
);
}
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/af.json
Original file line number Diff line number Diff line change
Expand Up @@ -4805,6 +4805,7 @@
"Upload Manual Update File": "",
"Upload New Image": "",
"Upload SSH Key": "",
"Uploading": "",
"Uploading Image": "",
"Uploading and Applying Config": "",
"Uploading file...": "",
Expand Down Expand Up @@ -4997,6 +4998,7 @@
"Volume is in use.": "",
"Volume removed": "",
"Volume size cannot be zero.": "",
"Volume with this name already exists.": "",
"Volumes": "",
"WARNING": "",
"WARNING: A failover will temporarily interrupt system services.": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -4805,6 +4805,7 @@
"Upload Manual Update File": "",
"Upload New Image": "",
"Upload SSH Key": "",
"Uploading": "",
"Uploading Image": "",
"Uploading and Applying Config": "",
"Uploading file...": "",
Expand Down Expand Up @@ -4997,6 +4998,7 @@
"Volume is in use.": "",
"Volume removed": "",
"Volume size cannot be zero.": "",
"Volume with this name already exists.": "",
"Volumes": "",
"WARNING": "",
"WARNING: A failover will temporarily interrupt system services.": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/ast.json
Original file line number Diff line number Diff line change
Expand Up @@ -4805,6 +4805,7 @@
"Upload Manual Update File": "",
"Upload New Image": "",
"Upload SSH Key": "",
"Uploading": "",
"Uploading Image": "",
"Uploading and Applying Config": "",
"Uploading file...": "",
Expand Down Expand Up @@ -4997,6 +4998,7 @@
"Volume is in use.": "",
"Volume removed": "",
"Volume size cannot be zero.": "",
"Volume with this name already exists.": "",
"Volumes": "",
"WARNING": "",
"WARNING: A failover will temporarily interrupt system services.": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/az.json
Original file line number Diff line number Diff line change
Expand Up @@ -4805,6 +4805,7 @@
"Upload Manual Update File": "",
"Upload New Image": "",
"Upload SSH Key": "",
"Uploading": "",
"Uploading Image": "",
"Uploading and Applying Config": "",
"Uploading file...": "",
Expand Down Expand Up @@ -4997,6 +4998,7 @@
"Volume is in use.": "",
"Volume removed": "",
"Volume size cannot be zero.": "",
"Volume with this name already exists.": "",
"Volumes": "",
"WARNING": "",
"WARNING: A failover will temporarily interrupt system services.": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/be.json
Original file line number Diff line number Diff line change
Expand Up @@ -4805,6 +4805,7 @@
"Upload Manual Update File": "",
"Upload New Image": "",
"Upload SSH Key": "",
"Uploading": "",
"Uploading Image": "",
"Uploading and Applying Config": "",
"Uploading file...": "",
Expand Down Expand Up @@ -4997,6 +4998,7 @@
"Volume is in use.": "",
"Volume removed": "",
"Volume size cannot be zero.": "",
"Volume with this name already exists.": "",
"Volumes": "",
"WARNING": "",
"WARNING: A failover will temporarily interrupt system services.": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/bg.json
Original file line number Diff line number Diff line change
Expand Up @@ -4805,6 +4805,7 @@
"Upload Manual Update File": "",
"Upload New Image": "",
"Upload SSH Key": "",
"Uploading": "",
"Uploading Image": "",
"Uploading and Applying Config": "",
"Uploading file...": "",
Expand Down Expand Up @@ -4997,6 +4998,7 @@
"Volume is in use.": "",
"Volume removed": "",
"Volume size cannot be zero.": "",
"Volume with this name already exists.": "",
"Volumes": "",
"WARNING": "",
"WARNING: A failover will temporarily interrupt system services.": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/bn.json
Original file line number Diff line number Diff line change
Expand Up @@ -4805,6 +4805,7 @@
"Upload Manual Update File": "",
"Upload New Image": "",
"Upload SSH Key": "",
"Uploading": "",
"Uploading Image": "",
"Uploading and Applying Config": "",
"Uploading file...": "",
Expand Down Expand Up @@ -4997,6 +4998,7 @@
"Volume is in use.": "",
"Volume removed": "",
"Volume size cannot be zero.": "",
"Volume with this name already exists.": "",
"Volumes": "",
"WARNING": "",
"WARNING: A failover will temporarily interrupt system services.": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/br.json
Original file line number Diff line number Diff line change
Expand Up @@ -4805,6 +4805,7 @@
"Upload Manual Update File": "",
"Upload New Image": "",
"Upload SSH Key": "",
"Uploading": "",
"Uploading Image": "",
"Uploading and Applying Config": "",
"Uploading file...": "",
Expand Down Expand Up @@ -4997,6 +4998,7 @@
"Volume is in use.": "",
"Volume removed": "",
"Volume size cannot be zero.": "",
"Volume with this name already exists.": "",
"Volumes": "",
"WARNING": "",
"WARNING: A failover will temporarily interrupt system services.": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/bs.json
Original file line number Diff line number Diff line change
Expand Up @@ -4805,6 +4805,7 @@
"Upload Manual Update File": "",
"Upload New Image": "",
"Upload SSH Key": "",
"Uploading": "",
"Uploading Image": "",
"Uploading and Applying Config": "",
"Uploading file...": "",
Expand Down Expand Up @@ -4997,6 +4998,7 @@
"Volume is in use.": "",
"Volume removed": "",
"Volume size cannot be zero.": "",
"Volume with this name already exists.": "",
"Volumes": "",
"WARNING": "",
"WARNING: A failover will temporarily interrupt system services.": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/ca.json
Original file line number Diff line number Diff line change
Expand Up @@ -4805,6 +4805,7 @@
"Upload Manual Update File": "",
"Upload New Image": "",
"Upload SSH Key": "",
"Uploading": "",
"Uploading Image": "",
"Uploading and Applying Config": "",
"Uploading file...": "",
Expand Down Expand Up @@ -4997,6 +4998,7 @@
"Volume is in use.": "",
"Volume removed": "",
"Volume size cannot be zero.": "",
"Volume with this name already exists.": "",
"Volumes": "",
"WARNING": "",
"WARNING: A failover will temporarily interrupt system services.": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -4122,6 +4122,7 @@
"Updating pool settings": "",
"Updating settings": "",
"Upload New Image": "",
"Uploading": "",
"Uploading Image": "",
"Use Absolute Paths": "",
"Use Debug": "",
Expand Down Expand Up @@ -4226,6 +4227,7 @@
"Volume": "",
"Volume is in use.": "",
"Volume removed": "",
"Volume with this name already exists.": "",
"Volumes": "",
"WARNING: A failover will temporarily interrupt system services.": "",
"WARNING: Adding data VDEVs with different numbers of disks is not recommended.": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/cy.json
Original file line number Diff line number Diff line change
Expand Up @@ -4805,6 +4805,7 @@
"Upload Manual Update File": "",
"Upload New Image": "",
"Upload SSH Key": "",
"Uploading": "",
"Uploading Image": "",
"Uploading and Applying Config": "",
"Uploading file...": "",
Expand Down Expand Up @@ -4997,6 +4998,7 @@
"Volume is in use.": "",
"Volume removed": "",
"Volume size cannot be zero.": "",
"Volume with this name already exists.": "",
"Volumes": "",
"WARNING": "",
"WARNING: A failover will temporarily interrupt system services.": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/da.json
Original file line number Diff line number Diff line change
Expand Up @@ -4805,6 +4805,7 @@
"Upload Manual Update File": "",
"Upload New Image": "",
"Upload SSH Key": "",
"Uploading": "",
"Uploading Image": "",
"Uploading and Applying Config": "",
"Uploading file...": "",
Expand Down Expand Up @@ -4997,6 +4998,7 @@
"Volume is in use.": "",
"Volume removed": "",
"Volume size cannot be zero.": "",
"Volume with this name already exists.": "",
"Volumes": "",
"WARNING": "",
"WARNING: A failover will temporarily interrupt system services.": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -3590,6 +3590,7 @@
"Upgrading Apps. Please check on the progress in Task Manager.": "",
"Upload Manual Update File": "",
"Upload New Image": "",
"Uploading": "",
"Uploading Image": "",
"Uploading and Applying Config": "",
"Usable Capacity": "",
Expand Down Expand Up @@ -3750,6 +3751,7 @@
"Volume Size": "",
"Volume is in use.": "",
"Volume removed": "",
"Volume with this name already exists.": "",
"Volumes": "",
"WARNING: Adding data VDEVs with different numbers of disks is not recommended.": "",
"WARNING: Based on the pool topology, {size} is the minimum recommended record size. Choosing a smaller size can reduce system performance.": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/dsb.json
Original file line number Diff line number Diff line change
Expand Up @@ -4805,6 +4805,7 @@
"Upload Manual Update File": "",
"Upload New Image": "",
"Upload SSH Key": "",
"Uploading": "",
"Uploading Image": "",
"Uploading and Applying Config": "",
"Uploading file...": "",
Expand Down Expand Up @@ -4997,6 +4998,7 @@
"Volume is in use.": "",
"Volume removed": "",
"Volume size cannot be zero.": "",
"Volume with this name already exists.": "",
"Volumes": "",
"WARNING": "",
"WARNING: A failover will temporarily interrupt system services.": "",
Expand Down
Loading
Loading